summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Mrázek <peterix@gmail.com>2013-08-10 18:34:08 +0200
committerPetr Mrázek <peterix@gmail.com>2013-08-11 01:07:15 +0200
commit1782d5ad9a646ca2a6fab90da5f04c879ddaecd4 (patch)
tree9537ecd66dad2fbcb083da2ed07191727a8e10ef
parentbf5f5091ef6daeaf7067f4fc8973eb068ddc52fc (diff)
downloadMultiMC-1782d5ad9a646ca2a6fab90da5f04c879ddaecd4.tar
MultiMC-1782d5ad9a646ca2a6fab90da5f04c879ddaecd4.tar.gz
MultiMC-1782d5ad9a646ca2a6fab90da5f04c879ddaecd4.tar.lz
MultiMC-1782d5ad9a646ca2a6fab90da5f04c879ddaecd4.tar.xz
MultiMC-1782d5ad9a646ca2a6fab90da5f04c879ddaecd4.zip
Implement icon picker, bring back raster icons.
-rw-r--r--CMakeLists.txt14
-rw-r--r--asset_test.cpp170
-rw-r--r--backend/CMakeLists.txt2
-rw-r--r--backend/IconListModel.cpp163
-rw-r--r--backend/IconListModel.h33
-rw-r--r--gui/IconPickerDialog.cpp88
-rw-r--r--gui/IconPickerDialog.h26
-rw-r--r--gui/IconPickerDialog.ui67
-rw-r--r--gui/iconcache.cpp127
-rw-r--r--gui/iconcache.h43
-rw-r--r--gui/instancemodel.cpp5
-rw-r--r--gui/mainwindow.cpp59
-rw-r--r--gui/mainwindow.h2
-rw-r--r--gui/mainwindow.ui20
-rw-r--r--gui/newinstancedialog.cpp31
-rw-r--r--gui/newinstancedialog.h3
-rw-r--r--main.cpp3
-rw-r--r--multimc.qrc83
-rw-r--r--resources/icons/instances/brick.pngbin0 -> 713 bytes
-rw-r--r--resources/icons/instances/chicken.pngbin0 -> 1181 bytes
-rw-r--r--resources/icons/instances/chicken128.pngbin0 -> 6369 bytes
-rw-r--r--resources/icons/instances/creeper.pngbin0 -> 1524 bytes
-rw-r--r--resources/icons/instances/creeper128.pngbin0 -> 9046 bytes
-rw-r--r--resources/icons/instances/derp.pngbin0 -> 5225 bytes
-rw-r--r--resources/icons/instances/diamond.pngbin0 -> 708 bytes
-rw-r--r--resources/icons/instances/dirt.pngbin0 -> 482 bytes
-rw-r--r--resources/icons/instances/enderman.pngbin0 -> 2429 bytes
-rw-r--r--resources/icons/instances/enderpearl.pngbin0 -> 2120 bytes
-rw-r--r--resources/icons/instances/enderpearl128.pngbin0 -> 21425 bytes
-rw-r--r--resources/icons/instances/ftb_glow.pngbin0 -> 1747 bytes
-rw-r--r--resources/icons/instances/ftb_glow128.pngbin0 -> 12708 bytes
-rw-r--r--resources/icons/instances/ftb_logo.pngbin0 -> 1607 bytes
-rw-r--r--resources/icons/instances/ftb_logo128.pngbin0 -> 7883 bytes
-rw-r--r--resources/icons/instances/gear.pngbin0 -> 2414 bytes
-rw-r--r--resources/icons/instances/gear128.pngbin0 -> 18321 bytes
-rw-r--r--resources/icons/instances/gold.pngbin0 -> 978 bytes
-rw-r--r--resources/icons/instances/grass.pngbin0 -> 618 bytes
-rw-r--r--resources/icons/instances/herobrine.pngbin0 -> 1034 bytes
-rw-r--r--resources/icons/instances/herobrine128.pngbin0 -> 4937 bytes
-rw-r--r--resources/icons/instances/infinity.pngbin0 -> 1714 bytes
-rw-r--r--resources/icons/instances/infinity128.pngbin0 -> 9237 bytes
-rw-r--r--resources/icons/instances/iron.pngbin0 -> 532 bytes
-rw-r--r--resources/icons/instances/magitech.pngbin0 -> 2646 bytes
-rw-r--r--resources/icons/instances/magitech128.pngbin0 -> 23097 bytes
-rw-r--r--resources/icons/instances/meat.pngbin0 -> 1514 bytes
-rw-r--r--resources/icons/instances/meat128.pngbin0 -> 10583 bytes
-rw-r--r--resources/icons/instances/netherstar.pngbin0 -> 1942 bytes
-rw-r--r--resources/icons/instances/netherstar128.pngbin0 -> 14062 bytes
-rw-r--r--resources/icons/instances/planks.pngbin0 -> 461 bytes
-rw-r--r--resources/icons/instances/skeleton.pngbin0 -> 696 bytes
-rw-r--r--resources/icons/instances/skeleton128.pngbin0 -> 3673 bytes
-rw-r--r--resources/icons/instances/squarecreeper.pngbin0 -> 1623 bytes
-rw-r--r--resources/icons/instances/squarecreeper128.pngbin0 -> 9136 bytes
-rw-r--r--resources/icons/instances/steve.pngbin0 -> 969 bytes
-rw-r--r--resources/icons/instances/steve128.pngbin0 -> 4312 bytes
-rw-r--r--resources/icons/instances/stone.pngbin0 -> 438 bytes
-rw-r--r--resources/icons/instances/tnt.pngbin0 -> 378 bytes
-rw-r--r--resources/icons/instances_svg/clucker.svg (renamed from resources/icons/instances/clucker.svg)0
-rw-r--r--resources/icons/instances_svg/creeper.svg (renamed from resources/icons/instances/creeper.svg)0
-rw-r--r--resources/icons/instances_svg/enderpearl.svg (renamed from resources/icons/instances/enderpearl.svg)0
-rw-r--r--resources/icons/instances_svg/ftb-glow.svg (renamed from resources/icons/instances/ftb-glow.svg)0
-rw-r--r--resources/icons/instances_svg/ftb-logo.svg (renamed from resources/icons/instances/ftb-logo.svg)0
-rw-r--r--resources/icons/instances_svg/gear.svg (renamed from resources/icons/instances/gear.svg)0
-rw-r--r--resources/icons/instances_svg/herobrine.svg (renamed from resources/icons/instances/herobrine.svg)0
-rw-r--r--resources/icons/instances_svg/magitech.svg (renamed from resources/icons/instances/magitech.svg)0
-rw-r--r--resources/icons/instances_svg/meat.svg (renamed from resources/icons/instances/meat.svg)0
-rw-r--r--resources/icons/instances_svg/netherstar.svg (renamed from resources/icons/instances/netherstar.svg)0
-rw-r--r--resources/icons/instances_svg/pskeleton.svg581
-rw-r--r--resources/icons/instances_svg/skeleton.svg (renamed from resources/icons/instances/skeleton.svg)0
-rw-r--r--resources/icons/instances_svg/squarecreeper.svg (renamed from resources/icons/instances/squarecreeper.svg)0
-rw-r--r--resources/icons/instances_svg/steve.svg (renamed from resources/icons/instances/steve.svg)0
-rw-r--r--resources/icons/toolbar/NewsIcon.pngbin0 -> 1173 bytes
-rw-r--r--resources/icons/toolbar/ReportBug.pngbin0 -> 1180 bytes
-rw-r--r--resources/icons/toolbar_svg/bug.svg (renamed from resources/icons/toolbar/bug.svg)0
-rw-r--r--resources/icons/toolbar_svg/news.svg (renamed from resources/icons/toolbar/news.svg)0
75 files changed, 1097 insertions, 423 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e858d888..d907e152 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -176,8 +176,8 @@ gui/instancemodel.h
gui/instancedelegate.h
gui/versionselectdialog.h
gui/lwjglselectdialog.h
-gui/iconcache.h
gui/instancesettings.h
+gui/IconPickerDialog.h
java/annotations.h
java/classfile.h
@@ -209,8 +209,8 @@ gui/instancemodel.cpp
gui/instancedelegate.cpp
gui/versionselectdialog.cpp
gui/lwjglselectdialog.cpp
-gui/iconcache.cpp
gui/instancesettings.cpp
+gui/IconPickerDialog.cpp
java/javautils.cpp
java/annotations.cpp
@@ -232,6 +232,7 @@ gui/consolewindow.ui
gui/versionselectdialog.ui
gui/lwjglselectdialog.ui
gui/instancesettings.ui
+gui/IconPickerDialog.ui
)
@@ -284,15 +285,6 @@ IF(BUILD_KEYRING_TEST)
TARGET_LINK_LIBRARIES(Test libUtil libSettings)
ENDIF()
-option(BUILD_ASSET_TEST "Build the asset sync test binary" OFF)
-IF(BUILD_ASSET_TEST)
- # test.cpp
- ADD_EXECUTABLE(AssetTest asset_test.cpp)
- QT5_USE_MODULES(AssetTest Core Network)
- TARGET_LINK_LIBRARIES(AssetTest libUtil backend libSettings)
-ENDIF()
-
-
################################ INSTALLATION AND PACKAGING ################################
# use QtCreator's QTDIR var
IF(DEFINED ENV{QTDIR})
diff --git a/asset_test.cpp b/asset_test.cpp
deleted file mode 100644
index 90da314f..00000000
--- a/asset_test.cpp
+++ /dev/null
@@ -1,170 +0,0 @@
-#include <QString>
-#include <QDebug>
-#include <QtXml/QtXml>
-
-#include "dlqueue.h"
-
-inline QDomElement getDomElementByTagName(QDomElement parent, QString tagname)
-{
- QDomNodeList elementList = parent.elementsByTagName(tagname);
- if (elementList.count())
- return elementList.at(0).toElement();
- else
- return QDomElement();
-}
-
-class ThreadedDeleter : public QThread
-{
- Q_OBJECT
-public:
- void run()
- {
- QDirIterator iter(m_base, QDirIterator::Subdirectories);
- QStringList nuke_list;
- int base_length = m_base.length();
- while (iter.hasNext())
- {
- QString filename = iter.next();
- QFileInfo current(filename);
- // we keep the dirs... whatever
- if(current.isDir())
- continue;
- QString trimmedf = filename;
- trimmedf.remove(0, base_length + 1);
- if(m_whitelist.contains(trimmedf))
- {
- //qDebug() << trimmedf << " gets to live";
- }
- else
- {
- // DO NOT TOLERATE JUNK
- //qDebug() << trimmedf << " dies";
- QFile f (filename);
- f.remove();
- }
- }
- };
- QString m_base;
- QStringList m_whitelist;
-};
-
-class NukeAndPaveJob: public Job
-{
- Q_OBJECT
-public:
-
- explicit NukeAndPaveJob(QString base, QStringList whitelist)
- :Job()
- {
- QDir dir(base);
- deleterThread.m_base = dir.absolutePath();
- deleterThread.m_whitelist = whitelist;
- };
-public slots:
- virtual void start()
- {
- connect(&deleterThread, SIGNAL(finished()), SLOT(threadFinished()));
- deleterThread.start();
- };
- void threadFinished()
- {
- emit finish();
- }
-private:
- ThreadedDeleter deleterThread;
-};
-
-class DlMachine : public QObject
-{
- Q_OBJECT
-public slots:
- void filesFinished()
- {
- qApp->quit();
- }
-
- void fetchFinished()
- {
- QString prefix("http://s3.amazonaws.com/Minecraft.Resources/");
- QString fprefix("assets/");
- QStringList nuke_whitelist;
-
- JobPtr firstJob = index_job->getFirstJob();
- auto DlJob = firstJob.dynamicCast<DownloadJob>();
- QByteArray ba = DlJob->m_data;
-
- QString xmlErrorMsg;
- QDomDocument doc;
- if (!doc.setContent(ba, false, &xmlErrorMsg))
- {
- qDebug() << "Failed to process s3.amazonaws.com/Minecraft.Resources. XML error:" <<
- xmlErrorMsg << ba;
- }
- //QRegExp etag_match(".*([a-f0-9]{32}).*");
- QDomNodeList contents = doc.elementsByTagName("Contents");
-
- JobList *job = new JobList();
- connect(job, SIGNAL(finished()), SLOT(filesFinished()));
-
- for (int i = 0; i < contents.length(); i++)
- {
- QDomElement element = contents.at(i).toElement();
-
- if (element.isNull())
- continue;
-
- QDomElement keyElement = getDomElementByTagName(element, "Key");
- QDomElement lastmodElement = getDomElementByTagName(element, "LastModified");
- QDomElement etagElement = getDomElementByTagName(element, "ETag");
- QDomElement sizeElement = getDomElementByTagName(element, "Size");
-
- if (keyElement.isNull() || lastmodElement.isNull() || etagElement.isNull() || sizeElement.isNull())
- continue;
-
- QString keyStr = keyElement.text();
- QString lastModStr = lastmodElement.text();
- QString etagStr = etagElement.text();
- QString sizeStr = sizeElement.text();
-
- //Filter folder keys
- if (sizeStr == "0")
- continue;
-
- QString trimmedEtag = etagStr.remove('"');
- job->add(DownloadJob::create(QUrl(prefix + keyStr),fprefix + keyStr, trimmedEtag));
- nuke_whitelist.append(keyStr);
- }
- job->add(JobPtr(new NukeAndPaveJob(fprefix, nuke_whitelist)));
- files_job.reset(job);
- dl.enqueue(files_job);
- }
- void fetchStarted()
- {
- qDebug() << "Started downloading!";
- }
-public:
- void start()
- {
- JobList *job = new JobList();
- job->add(DownloadJob::create(QUrl("http://s3.amazonaws.com/Minecraft.Resources/")));
- connect(job, SIGNAL(finished()), SLOT(fetchFinished()));
- connect(job, SIGNAL(started()), SLOT(fetchStarted()));
- index_job.reset(job);
- dl.enqueue(index_job);
- }
- JobListQueue dl;
- JobListPtr index_job;
- JobListPtr files_job;
-};
-
-int main(int argc, char *argv[])
-{
- QCoreApplication app(argc, argv);
-
- DlMachine dl;
- dl.start();
-
- return app.exec();
-}
-
-#include "asset_test.moc"
diff --git a/backend/CMakeLists.txt b/backend/CMakeLists.txt
index ea19fbbf..0d0df5e5 100644
--- a/backend/CMakeLists.txt
+++ b/backend/CMakeLists.txt
@@ -52,6 +52,7 @@ lists/InstanceList.h
lists/InstVersionList.h
lists/MinecraftVersionList.h
lists/LwjglVersionList.h
+IconListModel.h
# Tasks
tasks/Task.h
@@ -87,6 +88,7 @@ lists/InstanceList.cpp
lists/InstVersionList.cpp
lists/MinecraftVersionList.cpp
lists/LwjglVersionList.cpp
+IconListModel.cpp
# Tasks
tasks/Task.cpp
diff --git a/backend/IconListModel.cpp b/backend/IconListModel.cpp
new file mode 100644
index 00000000..2d2fb6cf
--- /dev/null
+++ b/backend/IconListModel.cpp
@@ -0,0 +1,163 @@
+#include "IconListModel.h"
+#include <pathutils.h>
+#include <QMap>
+#include <QEventLoop>
+#include <QDir>
+
+#define MAX_SIZE 1024
+IconList* IconList::m_Instance = 0;
+QMutex IconList::mutex;
+
+struct entry
+{
+ QString key;
+ QString name;
+ QIcon icon;
+ bool is_builtin;
+};
+
+class Private : public QObject
+{
+ Q_OBJECT
+public:
+ QMap<QString, int> index;
+ QVector<entry> icons;
+ Private()
+ {
+ }
+};
+
+
+IconList::IconList() : QAbstractListModel(), d(new Private())
+{
+ QDir instance_icons(":/icons/instances/");
+ auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name);
+ for(auto file_info: file_info_list)
+ {
+ QString key = file_info.baseName();
+ addIcon(key, key, file_info.absoluteFilePath(), true);
+ }
+
+ // FIXME: get from settings
+ ensurePathExists("icons/");
+ QDir user_icons("icons/");
+ file_info_list = user_icons.entryInfoList(QDir::Files, QDir::Name);
+ for(auto file_info: file_info_list)
+ {
+ QString filename = file_info.absoluteFilePath();
+ QString key = file_info.baseName();
+ addIcon(key, key, filename);
+ }
+}
+
+IconList::~IconList()
+{
+ delete d;
+ d = nullptr;
+}
+
+QVariant IconList::data ( const QModelIndex& index, int role ) const
+{
+ if(!index.isValid())
+ return QVariant();
+
+ int row = index.row();
+
+ if(row < 0 || row >= d->icons.size())
+ return QVariant();
+
+ switch(role)
+ {
+ case Qt::DecorationRole:
+ return d->icons[row].icon;
+ case Qt::DisplayRole:
+ return d->icons[row].name;
+ case Qt::UserRole:
+ return d->icons[row].key;
+ default:
+ return QVariant();
+ }
+}
+
+int IconList::rowCount ( const QModelIndex& parent ) const
+{
+ return d->icons.size();
+}
+
+bool IconList::addIcon ( QString key, QString name, QString path, bool is_builtin )
+{
+ auto iter = d->index.find(key);
+ if(iter != d->index.end())
+ {
+ if(d->icons[*iter].is_builtin) return false;
+
+ QIcon icon(path);
+ if(icon.isNull()) return false;
+
+ // replace the icon
+ d->icons[*iter] = {key, name, icon, is_builtin};
+ return true;
+ }
+ else
+ {
+ QIcon icon(path);
+ if(icon.isNull()) return false;
+
+ // add a new icon
+ d->icons.push_back({key, name, icon, is_builtin});
+ d->index[key] = d->icons.size() - 1;
+ return true;
+ }
+}
+
+
+QIcon IconList::getIcon ( QString key )
+{
+ int icon_index = getIconIndex(key);
+
+ if(icon_index != -1)
+ return d->icons[icon_index].icon;
+
+ // Fallback for icons that don't exist.
+ icon_index = getIconIndex("infinity");
+
+ if(icon_index != -1)
+ return d->icons[icon_index].icon;
+ return QIcon();
+}
+
+int IconList::getIconIndex ( QString key )
+{
+ if(key == "default")
+ key = "infinity";
+
+ auto iter = d->index.find(key);
+ if(iter != d->index.end())
+ return *iter;
+
+
+ return -1;
+}
+
+
+void IconList::drop()
+{
+ mutex.lock();
+ delete m_Instance;
+ m_Instance = 0;
+ mutex.unlock();
+}
+
+IconList* IconList::instance()
+{
+ if ( !m_Instance )
+ {
+ mutex.lock();
+ if ( !m_Instance )
+ m_Instance = new IconList;
+ mutex.unlock();
+ }
+ return m_Instance;
+}
+
+#include "IconListModel.moc" \ No newline at end of file
diff --git a/backend/IconListModel.h b/backend/IconListModel.h
new file mode 100644
index 00000000..31b05e64
--- /dev/null
+++ b/backend/IconListModel.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <QMutex>
+#include <QAbstractListModel>
+#include <QtGui/QIcon>
+
+class Private;
+
+class IconList : public QAbstractListModel
+{
+public:
+ static IconList* instance();
+ static void drop();
+ QIcon getIcon ( QString key );
+ int getIconIndex ( QString key );
+
+ virtual QVariant data ( const QModelIndex& index, int role = Qt::DisplayRole ) const;
+ virtual int rowCount ( const QModelIndex& parent = QModelIndex() ) const;
+
+ bool addIcon(QString key, QString name, QString path, bool is_builtin = false);
+
+
+private:
+ virtual ~IconList();
+ IconList();
+ // hide copy constructor
+ IconList ( const IconList & ) = delete;
+ // hide assign op
+ IconList& operator= ( const IconList & ) = delete;
+ static IconList* m_Instance;
+ static QMutex mutex;
+ Private* d;
+};
diff --git a/gui/IconPickerDialog.cpp b/gui/IconPickerDialog.cpp
new file mode 100644
index 00000000..27e7f3b6
--- /dev/null
+++ b/gui/IconPickerDialog.cpp
@@ -0,0 +1,88 @@
+#include "IconPickerDialog.h"
+#include "instancedelegate.h"
+#include "ui_IconPickerDialog.h"
+#include <IconListModel.h>
+
+IconPickerDialog::IconPickerDialog(QWidget *parent) :
+ QDialog(parent),
+ ui(new Ui::IconPickerDialog)
+{
+ ui->setupUi(this);
+ auto contentsWidget = ui->iconView;
+ contentsWidget->setViewMode(QListView::IconMode);
+ contentsWidget->setFlow(QListView::LeftToRight);
+ contentsWidget->setIconSize(QSize(48, 48));
+ contentsWidget->setMovement(QListView::Static);
+ contentsWidget->setResizeMode(QListView::Adjust);
+ contentsWidget->setSelectionMode(QAbstractItemView::SingleSelection);
+ contentsWidget->setSpacing(5);
+ contentsWidget->setWordWrap(false);
+ contentsWidget->setWrapping(true);
+ contentsWidget->setUniformItemSizes(true);
+ contentsWidget->setTextElideMode(Qt::ElideRight);
+ contentsWidget->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
+ contentsWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
+ contentsWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ contentsWidget->setItemDelegate(new ListViewDelegate());
+
+ IconList * list = IconList::instance();
+ contentsWidget->setModel(list);
+
+ connect
+ (
+ contentsWidget,
+ SIGNAL(doubleClicked(QModelIndex)),
+ SLOT(activated(QModelIndex))
+ );
+
+ connect
+ (
+ contentsWidget->selectionModel(),
+ SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
+ SLOT(selectionChanged(QItemSelection,QItemSelection))
+ );
+}
+
+void IconPickerDialog::activated ( QModelIndex index )
+{
+ selectedIconKey = index.data(Qt::UserRole).toString();
+ accept();
+}
+
+
+void IconPickerDialog::selectionChanged ( QItemSelection selected, QItemSelection deselected )
+{
+ if(selected.empty())
+ return;
+
+ QString key = selected.first().indexes().first().data(Qt::UserRole).toString();
+ if(!key.isEmpty())
+ selectedIconKey = key;
+}
+
+int IconPickerDialog::exec ( QString selection )
+{
+ IconList * list = IconList::instance();
+ auto contentsWidget = ui->iconView;
+ selectedIconKey = selection;
+
+
+ int index_nr = list->getIconIndex(selection);
+ auto model_index = list->index(index_nr);
+ contentsWidget->selectionModel()->select(model_index, QItemSelectionModel::Current | QItemSelectionModel::Select);
+
+ QMetaObject::invokeMethod(this, "delayed_scroll", Qt::QueuedConnection, Q_ARG(QModelIndex,model_index));
+ return QDialog::exec();
+}
+
+void IconPickerDialog::delayed_scroll ( QModelIndex model_index )
+{
+ auto contentsWidget = ui->iconView;
+ contentsWidget->scrollTo(model_index);
+}
+
+
+IconPickerDialog::~IconPickerDialog()
+{
+ delete ui;
+}
diff --git a/gui/IconPickerDialog.h b/gui/IconPickerDialog.h
new file mode 100644
index 00000000..c55f6ff2
--- /dev/null
+++ b/gui/IconPickerDialog.h
@@ -0,0 +1,26 @@
+#pragma once
+#include <QDialog>
+#include <QItemSelection>
+
+namespace Ui {
+class IconPickerDialog;
+}
+
+class IconPickerDialog : public QDialog
+{
+ Q_OBJECT
+
+public:
+ explicit IconPickerDialog(QWidget *parent = 0);
+ ~IconPickerDialog();
+ int exec(QString selection);
+ QString selectedIconKey;
+
+private:
+ Ui::IconPickerDialog *ui;
+
+private slots:
+ void selectionChanged ( QItemSelection,QItemSelection );
+ void activated ( QModelIndex );
+ void delayed_scroll ( QModelIndex );
+};
diff --git a/gui/IconPickerDialog.ui b/gui/IconPickerDialog.ui
new file mode 100644
index 00000000..c548edfb
--- /dev/null
+++ b/gui/IconPickerDialog.ui
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>IconPickerDialog</class>
+ <widget class="QDialog" name="IconPickerDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>676</width>
+ <height>555</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Pick icon</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QListView" name="iconView"/>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>IconPickerDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>248</x>
+ <y>254</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>IconPickerDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>316</x>
+ <y>260</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/gui/iconcache.cpp b/gui/iconcache.cpp
deleted file mode 100644
index 520a7839..00000000
--- a/gui/iconcache.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-#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
deleted file mode 100644
index 5c5e4142..00000000
--- a/gui/iconcache.h
+++ /dev/null
@@ -1,43 +0,0 @@
-#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 5d47ed2d..dbeba0da 100644
--- a/gui/instancemodel.cpp
+++ b/gui/instancemodel.cpp
@@ -1,7 +1,8 @@
#include "instancemodel.h"
#include <BaseInstance.h>
+#include <IconListModel.h>
#include <QIcon>
-#include "iconcache.h"
+//#include "iconcache.h"
InstanceModel::InstanceModel ( const InstanceList& instances, QObject *parent )
: QAbstractListModel ( parent ), m_instances ( &instances )
@@ -71,7 +72,7 @@ QVariant InstanceModel::data ( const QModelIndex& index, int role ) const
}
case Qt::DecorationRole:
{
- IconCache * ic = IconCache::instance();
+ IconList * ic = IconList::instance();
// FIXME: replace with an icon cache/renderer
/*
QString path = ":/icons/instances/";
diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp
index 4d6a510b..bed2b35f 100644
--- a/gui/mainwindow.cpp
+++ b/gui/mainwindow.cpp
@@ -62,6 +62,7 @@
#include "instancemodel.h"
#include "instancedelegate.h"
+#include "IconPickerDialog.h"
#include "lists/MinecraftVersionList.h"
#include "lists/LwjglVersionList.h"
@@ -178,23 +179,24 @@ void MainWindow::on_actionAddInstance_triggered()
waitLoop.exec();
}
- NewInstanceDialog *newInstDlg = new NewInstanceDialog ( this );
- if (!newInstDlg->exec())
+ NewInstanceDialog newInstDlg( this );
+ if (!newInstDlg.exec())
return;
BaseInstance *newInstance = NULL;
- QString instDirName = DirNameFromString(newInstDlg->instName());
+ QString instDirName = DirNameFromString(newInstDlg.instName());
QString instDir = PathCombine(globalSettings->get("InstanceDir").toString(), instDirName);
auto &loader = InstanceFactory::get();
- auto error = loader.createInstance(newInstance, newInstDlg->selectedVersion(), instDir);
+ auto error = loader.createInstance(newInstance, newInstDlg.selectedVersion(), instDir);
QString errorMsg = QString("Failed to create instance %1: ").arg(instDirName);
switch (error)
{
case InstanceFactory::NoCreateError:
- newInstance->setName(newInstDlg->instName());
+ newInstance->setName(newInstDlg.instName());
+ newInstance->setIconKey(newInstDlg.iconKey());
instList.add(InstancePtr(newInstance));
return;
@@ -215,23 +217,36 @@ void MainWindow::on_actionAddInstance_triggered()
}
}
-void MainWindow::on_actionChangeInstGroup_triggered()
+void MainWindow::on_actionChangeInstIcon_triggered()
{
BaseInstance* inst = selectedInstance();
- if(inst)
+ if(!inst)
+ return;
+
+ IconPickerDialog dlg(this);
+ dlg.exec(selectedInstance()->iconKey());
+ if(dlg.result() == QDialog::Accepted)
{
- bool ok = false;
- QString name ( inst->group() );
- QInputDialog dlg(this);
- dlg.result();
- name = QInputDialog::getText ( this, tr ( "Group name" ), tr ( "Enter a new group name." ),
- QLineEdit::Normal, name, &ok );
- if(ok)
- inst->setGroup(name);
+ selectedInstance()->setIconKey(dlg.selectedIconKey);
}
}
+void MainWindow::on_actionChangeInstGroup_triggered()
+{
+ BaseInstance* inst = selectedInstance();
+ if(!inst)
+ return;
+
+ bool ok = false;
+ QString name ( inst->group() );
+ name = QInputDialog::getText ( this, tr ( "Group name" ), tr ( "Enter a new group name." ),
+ QLineEdit::Normal, name, &ok );
+ if(ok)
+ inst->setGroup(name);
+}
+
+
void MainWindow::on_actionViewInstanceFolder_triggered()
{
QString str = globalSettings->get ( "InstanceDir" ).toString();
@@ -390,7 +405,8 @@ void MainWindow::doLogin(const QString& errorMsg)
return;
LoginDialog* loginDlg = new LoginDialog(this, errorMsg);
- if (loginDlg->exec())
+ loginDlg->exec();
+ if(loginDlg->result() == QDialog::Accepted)
{
UserInfo uInfo{loginDlg->getUsername(), loginDlg->getPassword()};
@@ -515,10 +531,10 @@ void MainWindow::on_actionChangeInstMCVersion_triggered()
BaseInstance *inst = selectedInstance();
- VersionSelectDialog *vselect = new VersionSelectDialog(inst->versionList(), this);
- if (vselect->exec() && vselect->selectedVersion())
+ VersionSelectDialog vselect(inst->versionList(), this);
+ if (vselect.exec() && vselect.selectedVersion())
{
- inst->setIntendedVersionId(vselect->selectedVersion()->descriptor());
+ inst->setIntendedVersionId(vselect.selectedVersion()->descriptor());
}
}
@@ -529,8 +545,9 @@ void MainWindow::on_actionChangeInstLWJGLVersion_triggered()
if (!inst)
return;
- LWJGLSelectDialog *lselect = new LWJGLSelectDialog(this);
- if (lselect->exec())
+ LWJGLSelectDialog lselect(this);
+ lselect.exec();
+ if (lselect.result() == QDialog::Accepted)
{
}
diff --git a/gui/mainwindow.h b/gui/mainwindow.h
index 2a490ee5..efcbc80c 100644
--- a/gui/mainwindow.h
+++ b/gui/mainwindow.h
@@ -63,6 +63,8 @@ private slots:
void on_actionChangeInstGroup_triggered();
+ void on_actionChangeInstIcon_triggered();
+
void on_actionViewInstanceFolder_triggered();
void on_actionViewSelectedInstFolder_triggered();
diff --git a/gui/mainwindow.ui b/gui/mainwindow.ui
index e6a82635..ae34bf51 100644
--- a/gui/mainwindow.ui
+++ b/gui/mainwindow.ui
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>692</width>
- <height>596</height>
+ <width>688</width>
+ <height>650</height>
</rect>
</property>
<property name="windowTitle">
@@ -71,6 +71,9 @@
<property name="windowTitle">
<string>Instance Toolbar</string>
</property>
+ <property name="allowedAreas">
+ <set>Qt::LeftToolBarArea|Qt::RightToolBarArea</set>
+ </property>
<property name="floatable">
<bool>false</bool>
</property>
@@ -275,7 +278,7 @@
</action>
<action name="actionChangeInstIcon">
<property name="enabled">
- <bool>false</bool>
+ <bool>true</bool>
</property>
<property name="text">
<string>Change Icon</string>
@@ -345,7 +348,7 @@
</action>
<action name="actionEditInstMods">
<property name="enabled">
- <bool>true</bool>
+ <bool>false</bool>
</property>
<property name="text">
<string>Edit Mods</string>
@@ -358,6 +361,9 @@
</property>
</action>
<action name="actionChangeInstMCVersion">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="text">
<string>Change Version</string>
</property>
@@ -369,6 +375,9 @@
</property>
</action>
<action name="actionChangeInstLWJGLVersion">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="text">
<string>Change LWJGL</string>
</property>
@@ -380,6 +389,9 @@
</property>
</action>
<action name="actionRebuildInstJar">
+ <property name="checkable">
+ <bool>false</bool>
+ </property>
<property name="enabled">
<bool>false</bool>
</property>
diff --git a/gui/newinstancedialog.cpp b/gui/newinstancedialog.cpp
index a5c902b4..38fbc2e3 100644
--- a/gui/newinstancedialog.cpp
+++ b/gui/newinstancedialog.cpp
@@ -22,9 +22,11 @@
#include "InstanceVersion.h"
#include "tasks/Task.h"
+#include <IconListModel.h>
#include "versionselectdialog.h"
#include "taskdialog.h"
+#include "IconPickerDialog.h"
#include <QLayout>
#include <QPushButton>
@@ -40,7 +42,7 @@ NewInstanceDialog::NewInstanceDialog(QWidget *parent) :
ui->setupUi(this);
resize(minimumSizeHint());
layout()->setSizeConstraint(QLayout::SetFixedSize);
-
+ /*
if (!MinecraftVersionList::getMainList().isLoaded())
{
TaskDialog *taskDlg = new TaskDialog(this);
@@ -48,7 +50,11 @@ NewInstanceDialog::NewInstanceDialog(QWidget *parent) :
loadTask->setParent(taskDlg);
taskDlg->exec(loadTask);
}
+ */
setSelectedVersion(MinecraftVersionList::getMainList().getLatestStable());
+ InstIconKey = "infinity";
+ IconList * list = IconList::instance();
+ ui->iconButton->setIcon(list->getIcon(InstIconKey));
}
NewInstanceDialog::~NewInstanceDialog()
@@ -85,8 +91,7 @@ QString NewInstanceDialog::instName() const
QString NewInstanceDialog::iconKey() const
{
- // TODO: Implement icon stuff.
- return "default";
+ return InstIconKey;
}
const InstVersion *NewInstanceDialog::selectedVersion() const
@@ -96,15 +101,29 @@ const InstVersion *NewInstanceDialog::selectedVersion() const
void NewInstanceDialog::on_btnChangeVersion_clicked()
{
- VersionSelectDialog *vselect = new VersionSelectDialog(&MinecraftVersionList::getMainList(), this);
- if (vselect->exec())
+ VersionSelectDialog vselect(&MinecraftVersionList::getMainList(), this);
+ vselect.exec();
+ if (vselect.result() == QDialog::Accepted)
{
- const InstVersion *version = vselect->selectedVersion();
+ const InstVersion *version = vselect.selectedVersion();
if (version)
setSelectedVersion(version);
}
}
+void NewInstanceDialog::on_iconButton_clicked()
+{
+ IconPickerDialog dlg;
+ dlg.exec(InstIconKey);
+
+ if(dlg.result() == QDialog::Accepted)
+ {
+ IconList * list = IconList::instance();
+ InstIconKey = dlg.selectedIconKey;
+ ui->iconButton->setIcon(list->getIcon(InstIconKey));
+ }
+}
+
void NewInstanceDialog::on_instNameTextBox_textChanged(const QString &arg1)
{
updateDialogState();
diff --git a/gui/newinstancedialog.h b/gui/newinstancedialog.h
index 4ea5f944..3e99c76a 100644
--- a/gui/newinstancedialog.h
+++ b/gui/newinstancedialog.h
@@ -45,13 +45,14 @@ public:
private slots:
void on_btnChangeVersion_clicked();
-
+ void on_iconButton_clicked();
void on_instNameTextBox_textChanged(const QString &arg1);
private:
Ui::NewInstanceDialog *ui;
const InstVersion *m_selectedVersion;
+ QString InstIconKey;
};
#endif // NEWINSTANCEDIALOG_H
diff --git a/main.cpp b/main.cpp
index 51516a81..eae6b4ba 100644
--- a/main.cpp
+++ b/main.cpp
@@ -83,7 +83,8 @@ private slots:
void doLogin(const QString &errorMsg)
{
LoginDialog* loginDlg = new LoginDialog(nullptr, errorMsg);
- if (loginDlg->exec())
+ loginDlg->exec();
+ if (loginDlg->result() == QDialog::Accepted)
{
UserInfo uInfo{loginDlg->getUsername(), loginDlg->getPassword()};
diff --git a/multimc.qrc b/multimc.qrc
index acd9efd2..5b02d9ba 100644
--- a/multimc.qrc
+++ b/multimc.qrc
@@ -1,40 +1,49 @@
<RCC>
- <qresource prefix="/icons/toolbar">
- <file alias="about">resources/icons/toolbar/about.png</file>
- <file alias="bug">resources/icons/toolbar/bug.svg</file>
- <file alias="centralmods">resources/icons/toolbar/centralmods.png</file>
- <file alias="checkupdate">resources/icons/toolbar/checkupdate.png</file>
- <file alias="help">resources/icons/toolbar/help.png</file>
- <file alias="new">resources/icons/toolbar/new.png</file>
- <file alias="news">resources/icons/toolbar/news.svg</file>
- <file alias="refresh">resources/icons/toolbar/refresh.png</file>
- <file alias="settings">resources/icons/toolbar/settings.png</file>
- <file alias="viewfolder">resources/icons/toolbar/viewfolder.png</file>
- </qresource>
- <qresource prefix="/icons/instances">
- <file alias="chicken">resources/icons/instances/clucker.svg</file>
- <file alias="creeper">resources/icons/instances/creeper.svg</file>
- <file alias="enderpearl">resources/icons/instances/enderpearl.svg</file>
- <file alias="ftb-glow">resources/icons/instances/ftb-glow.svg</file>
- <file alias="ftb-logo">resources/icons/instances/ftb-logo.svg</file>
- <file alias="gear">resources/icons/instances/gear.svg</file>
- <file alias="herobrine">resources/icons/instances/herobrine.svg</file>
- <file alias="magitech">resources/icons/instances/magitech.svg</file>
- <file alias="meat">resources/icons/instances/meat.svg</file>
- <file alias="netherstar">resources/icons/instances/netherstar.svg</file>
- <file alias="skeleton">resources/icons/instances/skeleton.svg</file>
- <file alias="squarecreeper">resources/icons/instances/squarecreeper.svg</file>
- <file alias="steve">resources/icons/instances/steve.svg</file>
- <file alias="infinity">resources/icons/multimc.svg</file>
- </qresource>
- <qresource prefix="/launcher">
- <file alias="launcher.jar">resources/MultiMCLauncher.jar</file>
- </qresource>
- <qresource prefix="/icons/multimc">
- <file alias="scalable/apps/multimc.svg">resources/icons/multimc.svg</file>
- <file alias="index.theme">resources/XdgIcon.theme</file>
- </qresource>
+ <qresource prefix="/icons/toolbar">
+ <file alias="about">resources/icons/toolbar/about.png</file>
+ <file alias="bug">resources/icons/toolbar/ReportBug.png</file>
+ <file alias="centralmods">resources/icons/toolbar/centralmods.png</file>
+ <file alias="checkupdate">resources/icons/toolbar/checkupdate.png</file>
+ <file alias="help">resources/icons/toolbar/help.png</file>
+ <file alias="new">resources/icons/toolbar/new.png</file>
+ <file alias="news">resources/icons/toolbar/NewsIcon.png</file>
+ <file alias="refresh">resources/icons/toolbar/refresh.png</file>
+ <file alias="settings">resources/icons/toolbar/settings.png</file>
+ <file alias="viewfolder">resources/icons/toolbar/viewfolder.png</file>
+ </qresource>
+ <qresource prefix="/icons/instances">
+ <file alias="brick">resources/icons/instances/brick.png</file>
+ <file alias="chicken">resources/icons/instances/chicken128.png</file>
+ <file alias="creeper">resources/icons/instances/creeper128.png</file>
+ <file alias="derp">resources/icons/instances/derp.png</file>
+ <file alias="diamond">resources/icons/instances/diamond.png</file>
+ <file alias="dirt">resources/icons/instances/dirt.png</file>
+ <file alias="enderman">resources/icons/instances/enderman.png</file>
+ <file alias="enderpearl">resources/icons/instances/enderpearl128.png</file>
+ <file alias="ftb-glow">resources/icons/instances/ftb_glow128.png</file>
+ <file alias="ftb-logo">resources/icons/instances/ftb_logo128.png</file>
+ <file alias="gear">resources/icons/instances/gear128.png</file>
+ <file alias="gold">resources/icons/instances/gold.png</file>
+ <file alias="herobrine">resources/icons/instances/herobrine128.png</file>
+ <file alias="infinity">resources/icons/instances/infinity128.png</file>
+ <file alias="magitech">resources/icons/instances/magitech128.png</file>
+ <file alias="meat">resources/icons/instances/meat128.png</file>
+ <file alias="netherstar">resources/icons/instances/netherstar128.png</file>
+ <file alias="planks">resources/icons/instances/planks.png</file>
+ <file alias="skeleton">resources/icons/instances/skeleton128.png</file>
+ <file alias="squarecreeper">resources/icons/instances/squarecreeper128.png</file>
+ <file alias="steve">resources/icons/instances/steve128.png</file>
+ <file alias="stone">resources/icons/instances/stone.png</file>
+ <file alias="tnt">resources/icons/instances/tnt.png</file>
+ </qresource>
+ <qresource prefix="/launcher">
+ <file alias="launcher.jar">resources/MultiMCLauncher.jar</file>
+ </qresource>
+ <qresource prefix="/icons/multimc">
+ <file alias="scalable/apps/multimc.svg">resources/icons/multimc.svg</file>
+ <file alias="index.theme">resources/XdgIcon.theme</file>
+ </qresource>
<qresource prefix="/backgrounds">
- <file alias="kitteh">resources/catbgrnd2.png</file>
- </qresource>
+ <file alias="kitteh">resources/catbgrnd2.png</file>
+ </qresource>
</RCC>
diff --git a/resources/icons/instances/brick.png b/resources/icons/instances/brick.png
new file mode 100644
index 00000000..0b534366
--- /dev/null
+++ b/resources/icons/instances/brick.png
Binary files differ
diff --git a/resources/icons/instances/chicken.png b/resources/icons/instances/chicken.png
new file mode 100644
index 00000000..f870467a
--- /dev/null
+++ b/resources/icons/instances/chicken.png
Binary files differ
diff --git a/resources/icons/instances/chicken128.png b/resources/icons/instances/chicken128.png
new file mode 100644
index 00000000..71f6dedc
--- /dev/null
+++ b/resources/icons/instances/chicken128.png
Binary files differ
diff --git a/resources/icons/instances/creeper.png b/resources/icons/instances/creeper.png
new file mode 100644
index 00000000..a67ecfc3
--- /dev/null
+++ b/resources/icons/instances/creeper.png
Binary files differ
diff --git a/resources/icons/instances/creeper128.png b/resources/icons/instances/creeper128.png
new file mode 100644
index 00000000..41b7d07d
--- /dev/null
+++ b/resources/icons/instances/creeper128.png
Binary files differ
diff --git a/resources/icons/instances/derp.png b/resources/icons/instances/derp.png
new file mode 100644
index 00000000..4c361942
--- /dev/null
+++ b/resources/icons/instances/derp.png
Binary files differ
diff --git a/resources/icons/instances/diamond.png b/resources/icons/instances/diamond.png
new file mode 100644
index 00000000..376ab901
--- /dev/null
+++ b/resources/icons/instances/diamond.png
Binary files differ
diff --git a/resources/icons/instances/dirt.png b/resources/icons/instances/dirt.png
new file mode 100644
index 00000000..9e19eb8f
--- /dev/null
+++ b/resources/icons/instances/dirt.png
Binary files differ
diff --git a/resources/icons/instances/enderman.png b/resources/icons/instances/enderman.png
new file mode 100644
index 00000000..9f3a72b3
--- /dev/null
+++ b/resources/icons/instances/enderman.png
Binary files differ
diff --git a/resources/icons/instances/enderpearl.png b/resources/icons/instances/enderpearl.png
new file mode 100644
index 00000000..a818eb8e
--- /dev/null
+++ b/resources/icons/instances/enderpearl.png
Binary files differ
diff --git a/resources/icons/instances/enderpearl128.png b/resources/icons/instances/enderpearl128.png
new file mode 100644
index 00000000..0a5bf91a
--- /dev/null
+++ b/resources/icons/instances/enderpearl128.png
Binary files differ
diff --git a/resources/icons/instances/ftb_glow.png b/resources/icons/instances/ftb_glow.png
new file mode 100644
index 00000000..c4e6fd5d
--- /dev/null
+++ b/resources/icons/instances/ftb_glow.png
Binary files differ
diff --git a/resources/icons/instances/ftb_glow128.png b/resources/icons/instances/ftb_glow128.png
new file mode 100644
index 00000000..86632b21
--- /dev/null
+++ b/resources/icons/instances/ftb_glow128.png
Binary files differ
diff --git a/resources/icons/instances/ftb_logo.png b/resources/icons/instances/ftb_logo.png
new file mode 100644
index 00000000..20df7171
--- /dev/null
+++ b/resources/icons/instances/ftb_logo.png
Binary files differ
diff --git a/resources/icons/instances/ftb_logo128.png b/resources/icons/instances/ftb_logo128.png
new file mode 100644
index 00000000..e725b7fe
--- /dev/null
+++ b/resources/icons/instances/ftb_logo128.png
Binary files differ
diff --git a/resources/icons/instances/gear.png b/resources/icons/instances/gear.png
new file mode 100644
index 00000000..da9ba2f9
--- /dev/null
+++ b/resources/icons/instances/gear.png
Binary files differ
diff --git a/resources/icons/instances/gear128.png b/resources/icons/instances/gear128.png
new file mode 100644
index 00000000..75c68a66
--- /dev/null
+++ b/resources/icons/instances/gear128.png
Binary files differ
diff --git a/resources/icons/instances/gold.png b/resources/icons/instances/gold.png
new file mode 100644
index 00000000..9bedda16
--- /dev/null
+++ b/resources/icons/instances/gold.png
Binary files differ
diff --git a/resources/icons/instances/grass.png b/resources/icons/instances/grass.png
new file mode 100644
index 00000000..f1694547
--- /dev/null
+++ b/resources/icons/instances/grass.png
Binary files differ
diff --git a/resources/icons/instances/herobrine.png b/resources/icons/instances/herobrine.png
new file mode 100644
index 00000000..e5460da3
--- /dev/null
+++ b/resources/icons/instances/herobrine.png
Binary files differ
diff --git a/resources/icons/instances/herobrine128.png b/resources/icons/instances/herobrine128.png
new file mode 100644
index 00000000..13f1494c
--- /dev/null
+++ b/resources/icons/instances/herobrine128.png
Binary files differ
diff --git a/resources/icons/instances/infinity.png b/resources/icons/instances/infinity.png
new file mode 100644
index 00000000..bd94a3dc
--- /dev/null
+++ b/resources/icons/instances/infinity.png
Binary files differ
diff --git a/resources/icons/instances/infinity128.png b/resources/icons/instances/infinity128.png
new file mode 100644
index 00000000..226847fb
--- /dev/null
+++ b/resources/icons/instances/infinity128.png
Binary files differ
diff --git a/resources/icons/instances/iron.png b/resources/icons/instances/iron.png
new file mode 100644
index 00000000..28960782
--- /dev/null
+++ b/resources/icons/instances/iron.png
Binary files differ
diff --git a/resources/icons/instances/magitech.png b/resources/icons/instances/magitech.png
new file mode 100644
index 00000000..6fd8ff60
--- /dev/null
+++ b/resources/icons/instances/magitech.png
Binary files differ
diff --git a/resources/icons/instances/magitech128.png b/resources/icons/instances/magitech128.png
new file mode 100644
index 00000000..0f81a199
--- /dev/null
+++ b/resources/icons/instances/magitech128.png
Binary files differ
diff --git a/resources/icons/instances/meat.png b/resources/icons/instances/meat.png
new file mode 100644
index 00000000..6694859d
--- /dev/null
+++ b/resources/icons/instances/meat.png
Binary files differ
diff --git a/resources/icons/instances/meat128.png b/resources/icons/instances/meat128.png
new file mode 100644
index 00000000..fefc9bf1
--- /dev/null
+++ b/resources/icons/instances/meat128.png
Binary files differ
diff --git a/resources/icons/instances/netherstar.png b/resources/icons/instances/netherstar.png
new file mode 100644
index 00000000..43cb5113
--- /dev/null
+++ b/resources/icons/instances/netherstar.png
Binary files differ
diff --git a/resources/icons/instances/netherstar128.png b/resources/icons/instances/netherstar128.png
new file mode 100644
index 00000000..132085f0
--- /dev/null
+++ b/resources/icons/instances/netherstar128.png
Binary files differ
diff --git a/resources/icons/instances/planks.png b/resources/icons/instances/planks.png
new file mode 100644
index 00000000..7fcf8467
--- /dev/null
+++ b/resources/icons/instances/planks.png
Binary files differ
diff --git a/resources/icons/instances/skeleton.png b/resources/icons/instances/skeleton.png
new file mode 100644
index 00000000..0c8d3505
--- /dev/null
+++ b/resources/icons/instances/skeleton.png
Binary files differ
diff --git a/resources/icons/instances/skeleton128.png b/resources/icons/instances/skeleton128.png
new file mode 100644
index 00000000..55fcf5a9
--- /dev/null
+++ b/resources/icons/instances/skeleton128.png
Binary files differ
diff --git a/resources/icons/instances/squarecreeper.png b/resources/icons/instances/squarecreeper.png
new file mode 100644
index 00000000..b78c4ae0
--- /dev/null
+++ b/resources/icons/instances/squarecreeper.png
Binary files differ
diff --git a/resources/icons/instances/squarecreeper128.png b/resources/icons/instances/squarecreeper128.png
new file mode 100644
index 00000000..c82d8406
--- /dev/null
+++ b/resources/icons/instances/squarecreeper128.png
Binary files differ
diff --git a/resources/icons/instances/steve.png b/resources/icons/instances/steve.png
new file mode 100644
index 00000000..07c6acde
--- /dev/null
+++ b/resources/icons/instances/steve.png
Binary files differ
diff --git a/resources/icons/instances/steve128.png b/resources/icons/instances/steve128.png
new file mode 100644
index 00000000..a07cbd2f
--- /dev/null
+++ b/resources/icons/instances/steve128.png
Binary files differ
diff --git a/resources/icons/instances/stone.png b/resources/icons/instances/stone.png
new file mode 100644
index 00000000..34f9a751
--- /dev/null
+++ b/resources/icons/instances/stone.png
Binary files differ
diff --git a/resources/icons/instances/tnt.png b/resources/icons/instances/tnt.png
new file mode 100644
index 00000000..e40d404d
--- /dev/null
+++ b/resources/icons/instances/tnt.png
Binary files differ
diff --git a/resources/icons/instances/clucker.svg b/resources/icons/instances_svg/clucker.svg
index 0c1727eb..0c1727eb 100644
--- a/resources/icons/instances/clucker.svg
+++ b/resources/icons/instances_svg/clucker.svg
diff --git a/resources/icons/instances/creeper.svg b/resources/icons/instances_svg/creeper.svg
index 2a2e39b6..2a2e39b6 100644
--- a/resources/icons/instances/creeper.svg
+++ b/resources/icons/instances_svg/creeper.svg
diff --git a/resources/icons/instances/enderpearl.svg b/resources/icons/instances_svg/enderpearl.svg
index ac9378f5..ac9378f5 100644
--- a/resources/icons/instances/enderpearl.svg
+++ b/resources/icons/instances_svg/enderpearl.svg
diff --git a/resources/icons/instances/ftb-glow.svg b/resources/icons/instances_svg/ftb-glow.svg
index be78c78e..be78c78e 100644
--- a/resources/icons/instances/ftb-glow.svg
+++ b/resources/icons/instances_svg/ftb-glow.svg
diff --git a/resources/icons/instances/ftb-logo.svg b/resources/icons/instances_svg/ftb-logo.svg
index 8cf73567..8cf73567 100644
--- a/resources/icons/instances/ftb-logo.svg
+++ b/resources/icons/instances_svg/ftb-logo.svg
diff --git a/resources/icons/instances/gear.svg b/resources/icons/instances_svg/gear.svg
index c0169aec..c0169aec 100644
--- a/resources/icons/instances/gear.svg
+++ b/resources/icons/instances_svg/gear.svg
diff --git a/resources/icons/instances/herobrine.svg b/resources/icons/instances_svg/herobrine.svg
index 7392ba36..7392ba36 100644
--- a/resources/icons/instances/herobrine.svg
+++ b/resources/icons/instances_svg/herobrine.svg
diff --git a/resources/icons/instances/magitech.svg b/resources/icons/instances_svg/magitech.svg
index c6dd6bc0..c6dd6bc0 100644
--- a/resources/icons/instances/magitech.svg
+++ b/resources/icons/instances_svg/magitech.svg
diff --git a/resources/icons/instances/meat.svg b/resources/icons/instances_svg/meat.svg
index 69a20073..69a20073 100644
--- a/resources/icons/instances/meat.svg
+++ b/resources/icons/instances_svg/meat.svg
diff --git a/resources/icons/instances/netherstar.svg b/resources/icons/instances_svg/netherstar.svg
index 4046e4ec..4046e4ec 100644
--- a/resources/icons/instances/netherstar.svg
+++ b/resources/icons/instances_svg/netherstar.svg
diff --git a/resources/icons/instances_svg/pskeleton.svg b/resources/icons/instances_svg/pskeleton.svg
new file mode 100644
index 00000000..c2783df8
--- /dev/null
+++ b/resources/icons/instances_svg/pskeleton.svg
@@ -0,0 +1,581 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="32"
+ height="32"
+ id="svg2">
+ <defs
+ id="defs4">
+ <filter
+ x="-0.18000001"
+ y="-0.36000001"
+ width="1.36"
+ height="1.72"
+ color-interpolation-filters="sRGB"
+ id="filter5719">
+ <feGaussianBlur
+ id="feGaussianBlur5721"
+ stdDeviation="0.15" />
+ </filter>
+ <filter
+ x="-0.20999999"
+ y="-0.28"
+ width="1.42"
+ height="1.5599999"
+ color-interpolation-filters="sRGB"
+ id="filter5723">
+ <feGaussianBlur
+ id="feGaussianBlur5725"
+ stdDeviation="0.35" />
+ </filter>
+ <filter
+ x="-0.1728"
+ y="-0.34560001"
+ width="1.3456"
+ height="1.6912"
+ color-interpolation-filters="sRGB"
+ id="filter5711">
+ <feGaussianBlur
+ id="feGaussianBlur5713"
+ stdDeviation="0.144" />
+ </filter>
+ <filter
+ x="-0.20999999"
+ y="-0.28"
+ width="1.42"
+ height="1.5599999"
+ color-interpolation-filters="sRGB"
+ id="filter5727">
+ <feGaussianBlur
+ id="feGaussianBlur5729"
+ stdDeviation="0.35" />
+ </filter>
+ <filter
+ x="-0.14708571"
+ y="-0.25740001"
+ width="1.2941715"
+ height="1.5148"
+ color-interpolation-filters="sRGB"
+ id="filter4028-6">
+ <feGaussianBlur
+ id="feGaussianBlur4030-9"
+ stdDeviation="0.429" />
+ </filter>
+ <filter
+ color-interpolation-filters="sRGB"
+ id="filter4056-6">
+ <feGaussianBlur
+ id="feGaussianBlur4058-6"
+ stdDeviation="0.676" />
+ </filter>
+ </defs>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="translate(0,-1020.3622)"
+ id="layer1">
+ <rect
+ width="24"
+ height="24"
+ x="3.9999998"
+ y="1024.3622"
+ id="rect4063-2"
+ style="fill:#999999;fill-opacity:1;stroke:none" />
+ <rect
+ width="26"
+ height="26"
+ x="3"
+ y="3"
+ transform="matrix(1.0769231,0,0,1.0769237,-1.2307693,1019.1314)"
+ id="rect4038-2"
+ style="fill:#4d4d4d;fill-opacity:1;stroke:none;filter:url(#filter4056-6)" />
+ <rect
+ width="20"
+ height="5.0000172"
+ x="5.9999995"
+ y="1041.3622"
+ id="rect3189-4"
+ style="fill:#494949;fill-opacity:1;stroke:none" />
+ <path
+ d="m 6.0000007,1041.3622 20.0000003,0 0,2 -18.0000003,0 0,3 -2,0 z"
+ id="path4034-6"
+ style="fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter4028-6)" />
+ <rect
+ width="8"
+ height="5.0000172"
+ x="5.9999995"
+ y="1035.3622"
+ id="rect3155-9"
+ style="fill:#494949;fill-opacity:1;stroke:none" />
+ <rect
+ width="8"
+ height="5.0000172"
+ x="18"
+ y="1035.3622"
+ id="rect3163-4"
+ style="fill:#494949;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="3.9999998"
+ y="1024.3622"
+ id="rect3009-1"
+ style="fill:#a1a1a1;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="6.9999995"
+ y="1024.3622"
+ id="rect3011-9"
+ style="fill:#9b9b9b;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="10"
+ y="1024.3622"
+ id="rect3013-0"
+ style="fill:#a3a3a3;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="13"
+ y="1024.3622"
+ id="rect3017-9"
+ style="fill:#919191;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="16"
+ y="1024.3622"
+ id="rect3019-6"
+ style="fill:#888888;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="19"
+ y="1024.3622"
+ id="rect3021-8"
+ style="fill:#8f8f8f;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="22"
+ y="1024.3622"
+ id="rect3023-6"
+ style="fill:#9b9b9b;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="25"
+ y="1024.3622"
+ id="rect3025-7"
+ style="fill:#989898;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="3.9999998"
+ y="1027.3622"
+ id="rect3027-7"
+ style="fill:#9b9b9b;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="6.9999995"
+ y="1027.3622"
+ id="rect3029-6"
+ style="fill:#9b9b9b;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="10"
+ y="1027.3622"
+ id="rect3031-0"
+ style="fill:#a3a3a3;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="10"
+ y="1027.3622"
+ id="rect3033-4"
+ style="fill:#9b9b9b;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="13"
+ y="1027.3622"
+ id="rect3035-4"
+ style="fill:#aaaaaa;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="16"
+ y="1027.3622"
+ id="rect3037-2"
+ style="fill:#c1c1c1;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="19"
+ y="1027.3622"
+ id="rect3039-4"
+ style="fill:#bebebe;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="22"
+ y="1027.3622"
+ id="rect3041-2"
+ style="fill:#9b9b9b;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="25"
+ y="1027.3622"
+ id="rect3043-1"
+ style="fill:#919191;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="3.9999998"
+ y="1030.3622"
+ id="rect3045-3"
+ style="fill:#9b9b9b;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="6.9999995"
+ y="1030.3622"
+ id="rect3047-1"
+ style="fill:#c7c7c7;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="10"
+ y="1030.3622"
+ id="rect3049-5"
+ style="fill:#a3a3a3;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="10"
+ y="1030.3622"
+ id="rect3051-9"
+ style="fill:#cacaca;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="13"
+ y="1030.3622"
+ id="rect3053-2"
+ style="fill:#d8d8d8;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="16"
+ y="1030.3622"
+ id="rect3055-9"
+ style="fill:#cfcfcf;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="19"
+ y="1030.3622"
+ id="rect3057-7"
+ style="fill:#cfcfcf;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="22"
+ y="1030.3622"
+ id="rect3059-2"
+ style="fill:#bababa;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="25"
+ y="1030.3622"
+ id="rect3061-7"
+ style="fill:#aaaaaa;fill-opacity:1;stroke:none" />
+ <path
+ d="m 6.0000007,1035.3622 8.0000003,0 0,2 -6.0000003,0 0,3 -2,0 z"
+ id="path4032-3"
+ style="fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter4028-6)" />
+ <rect
+ width="3"
+ height="3"
+ x="3.9999998"
+ y="1033.3622"
+ id="rect3063-8"
+ style="fill:#bababa;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="6.9999995"
+ y="1033.3622"
+ id="rect3065-6"
+ style="fill:#c4c4c4;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="10"
+ y="1033.3622"
+ id="rect3067-1"
+ style="fill:#a3a3a3;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="10"
+ y="1033.3622"
+ id="rect3069-9"
+ style="fill:#bababa;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="13"
+ y="1033.3622"
+ id="rect3071-7"
+ style="fill:#c1c1c1;fill-opacity:1;stroke:none" />
+ <path
+ d="m 18.000001,1035.3622 8,0 0,2 -6,0 0,3 -2,0 z"
+ id="path4036-6"
+ style="fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter4028-6)" />
+ <rect
+ width="3"
+ height="3"
+ x="16"
+ y="1033.3622"
+ id="rect3073-1"
+ style="fill:#afafaf;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="19"
+ y="1033.3622"
+ id="rect3075-8"
+ style="fill:#cacaca;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="22"
+ y="1033.3622"
+ id="rect3077-8"
+ style="fill:#aaaaaa;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="25"
+ y="1033.3622"
+ id="rect3079-2"
+ style="fill:#aaaaaa;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="3.9999998"
+ y="1036.3622"
+ id="rect3153-6"
+ style="fill:#c4c4c4;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="13"
+ y="1036.3622"
+ id="rect3159-7"
+ style="fill:#c4c4c4;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="16"
+ y="1036.3622"
+ id="rect3161-0"
+ style="fill:#cacaca;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="25"
+ y="1036.3622"
+ id="rect3167-3"
+ style="fill:#bababa;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="3.9999998"
+ y="1039.3622"
+ id="rect3169-4"
+ style="fill:#a7a7a7;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="6.9999995"
+ y="1039.3622"
+ id="rect3171-8"
+ style="fill:#c1c1c1;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="10"
+ y="1039.3622"
+ id="rect3173-5"
+ style="fill:#a3a3a3;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="10"
+ y="1039.3622"
+ id="rect3175-0"
+ style="fill:#cacaca;fill-opacity:1;stroke:none" />
+ <rect
+ width="6"
+ height="3"
+ x="13"
+ y="1039.3622"
+ id="rect3177-4"
+ style="fill:#828282;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="19"
+ y="1039.3622"
+ id="rect3181-9"
+ style="fill:#cacaca;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="22"
+ y="1039.3622"
+ id="rect3183-7"
+ style="fill:#aaaaaa;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="25"
+ y="1039.3622"
+ id="rect3185-6"
+ style="fill:#8f8f8f;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="3.9999998"
+ y="1042.3622"
+ id="rect3187-1"
+ style="fill:#9e9e9e;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="25"
+ y="1042.3622"
+ id="rect3203-8"
+ style="fill:#919191;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="3.9999998"
+ y="1045.3622"
+ id="rect3205-4"
+ style="fill:#828282;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="6.9999995"
+ y="1045.3622"
+ id="rect3207-2"
+ style="fill:#7f7f7f;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="10"
+ y="1045.3622"
+ id="rect3209-3"
+ style="fill:#a3a3a3;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="10"
+ y="1045.3622"
+ id="rect3211-3"
+ style="fill:#858585;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="13"
+ y="1045.3622"
+ id="rect3213-9"
+ style="fill:#858585;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="16"
+ y="1045.3622"
+ id="rect3215-7"
+ style="fill:#919191;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="19"
+ y="1045.3622"
+ id="rect3217-0"
+ style="fill:#858585;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="22"
+ y="1045.3622"
+ id="rect3219-4"
+ style="fill:#949494;fill-opacity:1;stroke:none" />
+ <rect
+ width="3"
+ height="3"
+ x="25"
+ y="1045.3622"
+ id="rect3221-5"
+ style="fill:#888888;fill-opacity:1;stroke:none" />
+ <path
+ d="m 4.0000007,1023.3622 -1,1 0,24 1,1 24.0000003,0 1,-1 0,-24 -1,-1 z m 0,1 24.0000003,0 0,24 -24.0000003,0 z"
+ id="rect3223-4"
+ style="fill:#333333;fill-opacity:1;stroke:none" />
+ <rect
+ width="4"
+ height="3"
+ x="7.9999995"
+ y="1036.3622"
+ id="rect4124-4"
+ style="fill:#008080;fill-opacity:1;stroke:none;filter:url(#filter5727)" />
+ <rect
+ width="2"
+ height="1"
+ x="9"
+ y="1037.3622"
+ id="rect4084-3"
+ style="fill:#00ffff;fill-opacity:1;stroke:none;filter:url(#filter5711)" />
+ <rect
+ width="4"
+ height="3"
+ x="20"
+ y="1036.3622"
+ id="rect4124-9-2"
+ style="fill:#008080;fill-opacity:1;stroke:none;filter:url(#filter5723)" />
+ <rect
+ width="2"
+ height="1"
+ x="21"
+ y="1037.3622"
+ id="rect4086-7"
+ style="fill:#00ffff;fill-opacity:1;stroke:none;filter:url(#filter5719)" />
+ </g>
+</svg>
diff --git a/resources/icons/instances/skeleton.svg b/resources/icons/instances_svg/skeleton.svg
index 5d55f272..5d55f272 100644
--- a/resources/icons/instances/skeleton.svg
+++ b/resources/icons/instances_svg/skeleton.svg
diff --git a/resources/icons/instances/squarecreeper.svg b/resources/icons/instances_svg/squarecreeper.svg
index a1b0f4d1..a1b0f4d1 100644
--- a/resources/icons/instances/squarecreeper.svg
+++ b/resources/icons/instances_svg/squarecreeper.svg
diff --git a/resources/icons/instances/steve.svg b/resources/icons/instances_svg/steve.svg
index 2233272c..2233272c 100644
--- a/resources/icons/instances/steve.svg
+++ b/resources/icons/instances_svg/steve.svg
diff --git a/resources/icons/toolbar/NewsIcon.png b/resources/icons/toolbar/NewsIcon.png
new file mode 100644
index 00000000..1953bf7b
--- /dev/null
+++ b/resources/icons/toolbar/NewsIcon.png
Binary files differ
diff --git a/resources/icons/toolbar/ReportBug.png b/resources/icons/toolbar/ReportBug.png
new file mode 100644
index 00000000..90481bba
--- /dev/null
+++ b/resources/icons/toolbar/ReportBug.png
Binary files differ
diff --git a/resources/icons/toolbar/bug.svg b/resources/icons/toolbar_svg/bug.svg
index 0534cbef..0534cbef 100644
--- a/resources/icons/toolbar/bug.svg
+++ b/resources/icons/toolbar_svg/bug.svg
diff --git a/resources/icons/toolbar/news.svg b/resources/icons/toolbar_svg/news.svg
index 67a370df..67a370df 100644
--- a/resources/icons/toolbar/news.svg
+++ b/resources/icons/toolbar_svg/news.svg