summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2013-03-20 07:59:35 +0100
committerPetr Mrázek <peterix@gmail.com>2013-03-20 07:59:35 +0100
commite4806ab08d0293d395c1718ab16d28ba2ae9d0ed (patch)
treed4a2a79461fb4215f556d9c08f93ba451f862560
parent7d7e4034f48b578c87a4651075c2b73dc236181b (diff)
downloadMultiMC-e4806ab08d0293d395c1718ab16d28ba2ae9d0ed.tar
MultiMC-e4806ab08d0293d395c1718ab16d28ba2ae9d0ed.tar.gz
MultiMC-e4806ab08d0293d395c1718ab16d28ba2ae9d0ed.tar.lz
MultiMC-e4806ab08d0293d395c1718ab16d28ba2ae9d0ed.tar.xz
MultiMC-e4806ab08d0293d395c1718ab16d28ba2ae9d0ed.zip
Add SVG icon rendering/cache
-rw-r--r--CMakeLists.txt5
-rw-r--r--gui/iconcache.cpp127
-rw-r--r--gui/iconcache.h43
-rw-r--r--gui/instancemodel.cpp7
-rw-r--r--gui/mainwindow.cpp1
-rw-r--r--resources/icons/instances/skeleton.svg40
6 files changed, 187 insertions, 36 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cf6e1aab..fad09575 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -31,7 +31,6 @@ ENDIF()
# First, include header overrides
include_directories(hacks)
-
######## 3rd Party Libs ########
# Find the required Qt parts
@@ -155,7 +154,7 @@ MESSAGE(STATUS "Job URL: ${MultiMC_JOB_URL}")
######## Configure header ########
configure_file("${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/include/config.h")
-
+include_directories(${PROJECT_BINARY_DIR}/include)
################################ FILES ################################
@@ -172,6 +171,7 @@ gui/aboutdialog.h
gui/consolewindow.h
gui/instancemodel.h
gui/instancedelegate.h
+gui/iconcache.h
multimc_pragma.h
@@ -200,6 +200,7 @@ gui/aboutdialog.cpp
gui/consolewindow.cpp
gui/instancemodel.cpp
gui/instancedelegate.cpp
+gui/iconcache.cpp
java/javautils.cpp
java/annotations.cpp
diff --git a/gui/iconcache.cpp b/gui/iconcache.cpp
new file mode 100644
index 00000000..520a7839
--- /dev/null
+++ b/gui/iconcache.cpp
@@ -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" \ No newline at end of file
diff --git a/gui/iconcache.h b/gui/iconcache.h
new file mode 100644
index 00000000..5c5e4142
--- /dev/null
+++ b/gui/iconcache.h
@@ -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;
+};
+ \ No newline at end of file
diff --git a/gui/instancemodel.cpp b/gui/instancemodel.cpp
index 3c96c8f0..8db985e8 100644
--- a/gui/instancemodel.cpp
+++ b/gui/instancemodel.cpp
@@ -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.
diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp
index 78f58713..5a915e8c 100644
--- a/gui/mainwindow.cpp
+++ b/gui/mainwindow.cpp
@@ -71,6 +71,7 @@ MainWindow::MainWindow ( QWidget *parent ) :
pal.setBrush(QPalette::Base, QBrush(QPixmap(QString::fromUtf8(":/backgrounds/kitteh"))));
view->setPalette(pal);
*/
+
view->setStyleSheet(
"QListView\
{\
diff --git a/resources/icons/instances/skeleton.svg b/resources/icons/instances/skeleton.svg
index b2da5a46..5d55f272 100644
--- a/resources/icons/instances/skeleton.svg
+++ b/resources/icons/instances/skeleton.svg
@@ -13,7 +13,7 @@
height="32"
id="svg2"
version="1.1"
- inkscape:version="0.48.3.1 r9886"
+ inkscape:version="0.48.4 r9939"
sodipodi:docname="skeleton.svg"
inkscape:export-filename="/home/peterix/projects/MultiMC4/src/resources/insticons/skeleton128.png"
inkscape:export-xdpi="360"
@@ -23,19 +23,6 @@
<filter
color-interpolation-filters="sRGB"
inkscape:collect="always"
- id="filter5719"
- x="-0.18000001"
- width="1.36"
- y="-0.36000001"
- height="1.72">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.15"
- id="feGaussianBlur5721" />
- </filter>
- <filter
- color-interpolation-filters="sRGB"
- inkscape:collect="always"
id="filter5723"
x="-0.20999999"
width="1.42"
@@ -49,19 +36,6 @@
<filter
color-interpolation-filters="sRGB"
inkscape:collect="always"
- id="filter5711"
- x="-0.1728"
- width="1.3456"
- y="-0.34560001"
- height="1.6912">
- <feGaussianBlur
- inkscape:collect="always"
- stdDeviation="0.144"
- id="feGaussianBlur5713" />
- </filter>
- <filter
- color-interpolation-filters="sRGB"
- inkscape:collect="always"
id="filter5727"
x="-0.20999999"
width="1.42"
@@ -103,12 +77,12 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="11.313708"
- inkscape:cx="17.044214"
- inkscape:cy="19.500236"
+ inkscape:cx="-18.309169"
+ inkscape:cy="22.958832"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
- inkscape:window-width="1607"
+ inkscape:window-width="1614"
inkscape:window-height="1030"
inkscape:window-x="1676"
inkscape:window-y="-3"
@@ -129,7 +103,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
- <dc:title></dc:title>
+ <dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@@ -612,7 +586,7 @@
x="7.9999995"
y="1036.3622" />
<rect
- style="fill:#00ffff;fill-opacity:1;stroke:none;filter:url(#filter5711)"
+ style="fill:#00ffff;fill-opacity:1;stroke:none;"
id="rect4084-3"
width="2"
height="1"
@@ -626,7 +600,7 @@
x="20"
y="1036.3622" />
<rect
- style="fill:#00ffff;fill-opacity:1;stroke:none;filter:url(#filter5719)"
+ style="fill:#00ffff;fill-opacity:1;stroke:none;"
id="rect4086-7"
width="2"
height="1"