NOISSUE allow using icon themes for instances and instance badges

This commit is contained in:
Petr Mrázek 2016-11-10 02:54:53 +01:00
parent 27e26a656b
commit f9d94a45ee
56 changed files with 165 additions and 131 deletions

View File

@ -25,15 +25,23 @@
#define MAX_SIZE 1024
IconList::IconList(QString builtinPath, QString path, QObject *parent) : QAbstractListModel(parent)
IconList::IconList(const QStringList &builtinPaths, QString path, QObject *parent) : QAbstractListModel(parent)
{
QSet<QString> builtinNames;
// add builtin icons
QDir instance_icons(builtinPath);
auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name);
for (auto file_info : file_info_list)
for(auto & builtinPath: builtinPaths)
{
QString key = file_info.baseName();
addIcon(key, key, file_info.absoluteFilePath(), IconType::Builtin);
QDir instance_icons(builtinPath);
auto file_info_list = instance_icons.entryInfoList(QDir::Files, QDir::Name);
for (auto file_info : file_info_list)
{
builtinNames.insert(file_info.baseName());
}
}
for(auto & builtinName : builtinNames)
{
addThemeIcon(builtinName);
}
m_watcher.reset(new QFileSystemWatcher());
@ -292,6 +300,33 @@ bool IconList::deleteIcon(const QString &key)
return false;
}
bool IconList::addThemeIcon(const QString& key)
{
auto iter = name_index.find(key);
if (iter != name_index.end())
{
auto &oldOne = icons[*iter];
oldOne.replace(Builtin, key);
dataChanged(index(*iter), index(*iter));
return true;
}
else
{
// add a new icon
beginInsertRows(QModelIndex(), icons.size(), icons.size());
{
MMCIcon mmc_icon;
mmc_icon.m_name = key;
mmc_icon.m_key = key;
mmc_icon.replace(Builtin, key);
icons.push_back(mmc_icon);
name_index[key] = icons.size() - 1;
}
endInsertRows();
return true;
}
}
bool IconList::addIcon(const QString &key, const QString &name, const QString &path, const IconType type)
{
// replace the icon even? is the input valid?

View File

@ -34,7 +34,7 @@ class MULTIMC_GUI_EXPORT IconList : public QAbstractListModel, public IIconList
{
Q_OBJECT
public:
explicit IconList(QString builtinPath, QString path, QObject *parent = 0);
explicit IconList(const QStringList &builtinPaths, QString path, QObject *parent = 0);
virtual ~IconList() {};
QIcon getIcon(const QString &key) const;
@ -44,6 +44,7 @@ public:
virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
virtual int rowCount(const QModelIndex &parent = QModelIndex()) const override;
bool addThemeIcon(const QString &key);
bool addIcon(const QString &key, const QString &name, const QString &path, const IconType type) override;
void saveIcon(const QString &key, const QString &path, const char * format) const override;
bool deleteIcon(const QString &key) override;

View File

@ -15,6 +15,7 @@
#include "MMCIcon.h"
#include <QFileInfo>
#include <xdgicon.h>
IconType operator--(IconType &t, int)
{
@ -58,7 +59,11 @@ QIcon MMCIcon::icon() const
{
if (m_current_type == IconType::ToBeDeleted)
return QIcon();
return m_images[m_current_type].icon;
auto & icon = m_images[m_current_type].icon;
if(!icon.isNull())
return icon;
// FIXME: inject this.
return XdgIcon::fromTheme(m_images[m_current_type].key);
}
void MMCIcon::remove(IconType rm_type)
@ -78,12 +83,22 @@ void MMCIcon::remove(IconType rm_type)
void MMCIcon::replace(IconType new_type, QIcon icon, QString path)
{
QFileInfo foo(path);
if (new_type > m_current_type || m_current_type == IconType::ToBeDeleted)
{
m_current_type = new_type;
}
m_images[new_type].icon = icon;
m_images[new_type].changed = foo.lastModified();
m_images[new_type].filename = path;
m_images[new_type].key = QString();
}
void MMCIcon::replace(IconType new_type, const QString& key)
{
if (new_type > m_current_type || m_current_type == IconType::ToBeDeleted)
{
m_current_type = new_type;
}
m_images[new_type].icon = QIcon();
m_images[new_type].filename = QString();
m_images[new_type].key = key;
}

View File

@ -24,11 +24,11 @@
struct MULTIMC_GUI_EXPORT MMCImage
{
QIcon icon;
QString key;
QString filename;
QDateTime changed;
bool present() const
{
return !icon.isNull();
return !icon.isNull() && !key.isEmpty();
}
};
@ -45,4 +45,5 @@ struct MULTIMC_GUI_EXPORT MMCIcon
QIcon icon() const;
void remove(IconType rm_type);
void replace(IconType new_type, QIcon icon, QString path = QString());
void replace(IconType new_type, const QString &key);
};

View File

@ -304,7 +304,6 @@ set(MULTIMC_QRCS
resources/pe_blue/pe_blue.qrc
resources/OSX/OSX.qrc
resources/iOS/iOS.qrc
resources/instances/instances.qrc
resources/versions/versions.qrc
resources/certs/certs.qrc
)

View File

@ -411,7 +411,13 @@ void MultiMC::initTranslations()
void MultiMC::initIcons()
{
auto setting = MMC->settings()->getSetting("IconsDir");
m_icons.reset(new IconList(QString(":/icons/instances/"), setting->get().toString()));
QStringList instFolders =
{
":/icons/multimc/32x32/instances/",
":/icons/multimc/50x50/instances/",
":/icons/multimc/128x128/instances/"
};
m_icons.reset(new IconList(instFolders, setting->get().toString()));
connect(setting.get(), &Setting::SettingChanged,[&](const Setting &, QVariant value)
{
m_icons->directoryChanged(value.toString());

View File

@ -23,8 +23,7 @@
#include "GroupView.h"
#include "BaseInstance.h"
#include "InstanceList.h"
QCache<QString, QPixmap> ListViewDelegate::m_pixmapCache;
#include <xdgicon.h>
// Origin: Qt
static void viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &height,
@ -110,47 +109,22 @@ void drawProgressOverlay(QPainter *painter, const QStyleOptionViewItemV4 &option
painter->restore();
}
void drawBadges(QPainter *painter, const QStyleOptionViewItemV4 &option, BaseInstance *instance)
void drawBadges(QPainter *painter, const QStyleOptionViewItemV4 &option, BaseInstance *instance, QIcon::Mode mode, QIcon::State state)
{
QList<QString> pixmaps;
if (instance->isRunning())
{
pixmaps.append("status-running");
}
else if (instance->hasCrashed())
else if (instance->hasCrashed() || instance->hasVersionBroken())
{
pixmaps.append("status-bad");
}
if (instance->hasVersionBroken())
{
pixmaps.append("broken");
}
if (instance->hasUpdateAvailable())
{
pixmaps.append("updateavailable");
pixmaps.append("checkupdate");
}
// begin easter eggs
if (instance->name().contains("btw", Qt::CaseInsensitive) ||
instance->name().contains("better then wolves", Qt::CaseInsensitive) ||
instance->name().contains("better than wolves", Qt::CaseInsensitive))
{
pixmaps.append("herobrine");
}
if (instance->name().contains("direwolf", Qt::CaseInsensitive))
{
pixmaps.append("enderman");
}
if (instance->name().contains("kitten", Qt::CaseInsensitive))
{
pixmaps.append("kitten");
}
if (instance->name().contains("derp", Qt::CaseInsensitive))
{
pixmaps.append("derp");
}
// end easter eggs
static const int itemSide = 24;
static const int spacing = 1;
const int itemsPerRow = qMax(1, qFloor(double(option.rect.width() + spacing) / double(itemSide + spacing)));
@ -165,11 +139,18 @@ void drawBadges(QPainter *painter, const QStyleOptionViewItemV4 &option, BaseIns
{
return;
}
const QPixmap pixmap = ListViewDelegate::requestBadgePixmap(it.next()).scaled(
itemSide, itemSide, Qt::KeepAspectRatio, Qt::FastTransformation);
painter->drawPixmap(option.rect.width() - x * itemSide + qMax(x - 1, 0) * spacing - itemSide,
y * itemSide + qMax(y - 1, 0) * spacing, itemSide, itemSide,
pixmap);
// FIXME: inject this.
auto icon = XdgIcon::fromTheme(it.next());
// opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state);
const QPixmap pixmap;
// itemSide
QRect badgeRect(
option.rect.width() - x * itemSide + qMax(x - 1, 0) * spacing - itemSide,
y * itemSide + qMax(y - 1, 0) * spacing,
itemSide,
itemSide
);
icon.paint(painter, badgeRect, Qt::AlignCenter, mode, state);
}
}
painter->translate(-option.rect.topLeft());
@ -274,15 +255,16 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
*/
}
// icon mode and state, also used for badges
QIcon::Mode mode = QIcon::Normal;
if (!(opt.state & QStyle::State_Enabled))
mode = QIcon::Disabled;
else if (opt.state & QStyle::State_Selected)
mode = QIcon::Selected;
QIcon::State state = opt.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
// draw the icon
{
QIcon::Mode mode = QIcon::Normal;
if (!(opt.state & QStyle::State_Enabled))
mode = QIcon::Disabled;
else if (opt.state & QStyle::State_Selected)
mode = QIcon::Selected;
QIcon::State state = opt.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
iconbox.setHeight(iconSize);
opt.icon.paint(painter, iconbox, Qt::AlignCenter, mode, state);
}
@ -329,7 +311,7 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti
.value<void *>();
if (instance)
{
drawBadges(painter, opt, instance);
drawBadges(painter, opt, instance, mode, state);
}
drawProgressOverlay(painter, opt, index.data(GroupViewRoles::ProgressValueRole).toInt(),
@ -359,11 +341,3 @@ QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option,
return sz;
}
QPixmap ListViewDelegate::requestBadgePixmap(const QString &key)
{
if (!m_pixmapCache.contains(key))
{
m_pixmapCache.insert(key, new QPixmap(":/icons/badges/" + key + ".png"));
}
return *m_pixmapCache.object(key);
}

View File

@ -23,13 +23,8 @@ class ListViewDelegate : public QStyledItemDelegate
public:
explicit ListViewDelegate(QObject *parent = 0);
static QPixmap requestBadgePixmap(const QString &key);
protected:
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
private:
static QCache<QString, QPixmap> m_pixmapCache;
};

View File

@ -13,7 +13,6 @@ int main(int argc, char *argv[])
{
case MultiMC::Initialized:
{
Q_INIT_RESOURCE(instances);
Q_INIT_RESOURCE(multimc);
Q_INIT_RESOURCE(backgrounds);
Q_INIT_RESOURCE(versions);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -1,51 +0,0 @@
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource prefix="/icons/instances">
<!-- Source: Mojang -->
<file alias="brick">brick.png</file>
<file alias="diamond">diamond.png</file>
<file alias="dirt">dirt.png</file>
<file alias="gold">gold.png</file>
<file alias="grass">grass.png</file>
<file alias="stone">stone.png</file>
<file alias="tnt">tnt.png</file>
<file alias="iron">iron.png</file>
<file alias="planks">planks.png</file>
<!-- Source: Unknown -->
<file alias="derp">derp.png</file>
<file alias="enderman">enderman.png</file>
<!-- Our own. -->
<file alias="chicken">chicken128.png</file>
<file alias="creeper">creeper128.png</file>
<file alias="enderpearl">enderpearl128.png</file>
<file alias="ftb-glow">ftb_glow128.png</file>
<file alias="ftb-logo">ftb_logo128.png</file>
<file alias="gear">gear128.png</file>
<file alias="herobrine">herobrine128.png</file>
<file alias="infinity">infinity128.png</file>
<file alias="magitech">magitech128.png</file>
<file alias="meat">meat128.png</file>
<file alias="netherstar">netherstar128.png</file>
<file alias="skeleton">skeleton128.png</file>
<file alias="squarecreeper">squarecreeper128.png</file>
<file alias="steve">steve128.png</file>
</qresource>
<qresource prefix="/icons/badges">
<!-- Source: see above -->
<file>enderman.png</file>
<file>herobrine.png</file>
<file>derp.png</file>
<file>status-running.png</file>
<file>status-bad.png</file>
<!-- Update. GPLv2, https://code.google.com/p/gnome-colors/ -->
<file>updateavailable.png</file>
<!-- Source: http://www.iconarchive.com/show/cat-icons-by-fasticon/Cat-Brown-icon.html -->
<file>kitten.png</file>
<!-- Source: http://www.iconarchive.com/show/crystal-clear-icons-by-everaldo/Filesystem-file-broken-icon.html -->
<file>broken.png</file>
</qresource>
</RCC>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 713 B

After

Width:  |  Height:  |  Size: 713 B

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 708 B

After

Width:  |  Height:  |  Size: 708 B

View File

Before

Width:  |  Height:  |  Size: 482 B

After

Width:  |  Height:  |  Size: 482 B

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 978 B

After

Width:  |  Height:  |  Size: 978 B

View File

Before

Width:  |  Height:  |  Size: 618 B

After

Width:  |  Height:  |  Size: 618 B

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

Before

Width:  |  Height:  |  Size: 532 B

After

Width:  |  Height:  |  Size: 532 B

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 461 B

After

Width:  |  Height:  |  Size: 461 B

View File

Before

Width:  |  Height:  |  Size: 696 B

After

Width:  |  Height:  |  Size: 696 B

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 969 B

After

Width:  |  Height:  |  Size: 969 B

View File

Before

Width:  |  Height:  |  Size: 438 B

After

Width:  |  Height:  |  Size: 438 B

View File

Before

Width:  |  Height:  |  Size: 378 B

After

Width:  |  Height:  |  Size: 378 B

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -2,14 +2,7 @@
Name=multimc
Comment=MultiMC Default Icons
Inherits=default
Directories=scalable/apps,8x8,16x16,22x22,24x24,32x32,48x48,scalable
[scalable/apps]
Size=48
Type=scalable
MinSize=1
MaxSize=512
Context=Applications
Directories=8x8,16x16,22x22,24x24,32x32,32x32/instances,48x48,50x50/instances,64x64,128x128/instances,256x256,scalable
[8x8]
Size=8
@ -26,12 +19,25 @@ Size=24
[32x32]
Size=32
[32x32/instances]
Size=32
MinSize=1
MaxSize=32
[48x48]
Size=48
[50x50/instances]
Size=50
[64x64]
Size=64
[128x128/instances]
Size=128
MinSize=33
MaxSize=128
[256x256]
Size=256

View File

@ -233,5 +233,59 @@
<!-- discord logo icon thing. from discord. traced from bitmap -->
<file>scalable/discord.svg</file>
</qresource>
<!-- instance icons -->
<file>32x32/instances/chicken.png</file>
<file>128x128/instances/chicken.png</file>
<file>32x32/instances/creeper.png</file>
<file>128x128/instances/creeper.png</file>
<file>32x32/instances/enderpearl.png</file>
<file>128x128/instances/enderpearl.png</file>
<file>32x32/instances/ftb_glow.png</file>
<file>128x128/instances/ftb_glow.png</file>
<file>32x32/instances/ftb_logo.png</file>
<file>128x128/instances/ftb_logo.png</file>
<file>32x32/instances/gear.png</file>
<file>128x128/instances/gear.png</file>
<file>32x32/instances/herobrine.png</file>
<file>128x128/instances/herobrine.png</file>
<file>32x32/instances/infinity.png</file>
<file>128x128/instances/infinity.png</file>
<file>32x32/instances/magitech.png</file>
<file>128x128/instances/magitech.png</file>
<file>32x32/instances/meat.png</file>
<file>128x128/instances/meat.png</file>
<file>32x32/instances/netherstar.png</file>
<file>128x128/instances/netherstar.png</file>
<file>32x32/instances/skeleton.png</file>
<file>128x128/instances/skeleton.png</file>
<file>32x32/instances/squarecreeper.png</file>
<file>128x128/instances/squarecreeper.png</file>
<file>32x32/instances/steve.png</file>
<file>128x128/instances/steve.png</file>
<file>32x32/instances/brick.png</file>
<file>32x32/instances/diamond.png</file>
<file>32x32/instances/dirt.png</file>
<file>32x32/instances/gold.png</file>
<file>32x32/instances/grass.png</file>
<file>32x32/instances/iron.png</file>
<file>32x32/instances/planks.png</file>
<file>32x32/instances/stone.png</file>
<file>32x32/instances/tnt.png</file>
<file>50x50/instances/enderman.png</file>
</qresource>
</RCC>