From 73fc9c79cff979e9023df0b1a77848c67b590681 Mon Sep 17 00:00:00 2001 From: Jan Dalheimer Date: Mon, 10 Mar 2014 17:38:27 +0100 Subject: [PATCH 1/2] Instance badges. Some easter eggs and one for broken so far. --- gui/groupview/InstanceDelegate.cpp | 85 +++++++++++++++++++++++++++-- gui/groupview/InstanceDelegate.h | 6 ++ logic/BaseInstance.cpp | 9 ++- logic/BaseInstance.h | 8 +-- logic/BaseInstance_p.h | 7 ++- logic/LegacyFTBInstance.cpp | 2 +- logic/LegacyInstance.cpp | 4 +- logic/NostalgiaInstance.cpp | 2 +- logic/OneSixFTBInstance.cpp | 2 +- logic/OneSixInstance.cpp | 8 +-- resources/instances/broken.png | Bin 0 -> 1589 bytes resources/instances/instances.qrc | 7 +++ resources/instances/kitten.png | Bin 0 -> 9107 bytes 13 files changed, 115 insertions(+), 25 deletions(-) create mode 100644 resources/instances/broken.png create mode 100644 resources/instances/kitten.png diff --git a/gui/groupview/InstanceDelegate.cpp b/gui/groupview/InstanceDelegate.cpp index 8a2737587..7ca4d7b4e 100644 --- a/gui/groupview/InstanceDelegate.cpp +++ b/gui/groupview/InstanceDelegate.cpp @@ -18,9 +18,13 @@ #include #include #include -#include +#include #include "GroupView.h" +#include "logic/BaseInstance.h" +#include "logic/lists/InstanceList.h" + +QCache ListViewDelegate::m_pixmapCache; // Origin: Qt static void viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &height, @@ -45,8 +49,6 @@ static void viewItemTextLayout(QTextLayout &textLayout, int lineWidth, qreal &he textLayout.endLayout(); } -#define QFIXED_MAX (INT_MAX / 256) - ListViewDelegate::ListViewDelegate(QObject *parent) : QStyledItemDelegate(parent) { } @@ -108,6 +110,64 @@ void drawProgressOverlay(QPainter *painter, const QStyleOptionViewItemV4 &option painter->restore(); } +void drawBadges(QPainter *painter, const QStyleOptionViewItemV4 &option, BaseInstance *instance) +{ + QList pixmaps; + for (auto flag : instance->flags()) + { + switch (flag) + { + case BaseInstance::VersionBrokenFlag: + pixmaps.append("broken"); + break; + } + } + + // 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))); + const int rows = qCeil((double)pixmaps.size() / (double)itemsPerRow); + QListIterator it(pixmaps); + painter->translate(option.rect.topLeft()); + for (int y = 0; y < rows; ++y) + { + for (int x = 0; x < itemsPerRow; ++x) + { + if (!it.hasNext()) + { + return; + } + const QPixmap pixmap = ListViewDelegate::requestPixmap(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); + } + } + painter->translate(-option.rect.topLeft()); +} + static QSize viewItemTextSize(const QStyleOptionViewItemV4 *option) { QStyle *style = option->widget ? option->widget->style() : QApplication::style(); @@ -257,8 +317,14 @@ void ListViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &opti line.draw(painter, position); } - drawProgressOverlay(painter, opt, - index.data(GroupViewRoles::ProgressValueRole).toInt(), + auto instance = (BaseInstance*)index.data(InstanceList::InstancePointerRole) + .value(); + if (instance) + { + drawBadges(painter, opt, instance); + } + + drawProgressOverlay(painter, opt, index.data(GroupViewRoles::ProgressValueRole).toInt(), index.data(GroupViewRoles::ProgressMaximumRole).toInt()); painter->restore(); @@ -284,3 +350,12 @@ QSize ListViewDelegate::sizeHint(const QStyleOptionViewItem &option, QSize sz(100, height); return sz; } + +QPixmap ListViewDelegate::requestPixmap(const QString &key) +{ + if (!m_pixmapCache.contains(key)) + { + m_pixmapCache.insert(key, new QPixmap(":/icons/badges/" + key + ".png")); + } + return *m_pixmapCache.object(key); +} diff --git a/gui/groupview/InstanceDelegate.h b/gui/groupview/InstanceDelegate.h index de2f429bb..9ab44864a 100644 --- a/gui/groupview/InstanceDelegate.h +++ b/gui/groupview/InstanceDelegate.h @@ -16,14 +16,20 @@ #pragma once #include +#include class ListViewDelegate : public QStyledItemDelegate { public: explicit ListViewDelegate(QObject *parent = 0); + static QPixmap requestPixmap(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 m_pixmapCache; }; diff --git a/logic/BaseInstance.cpp b/logic/BaseInstance.cpp index d78f1ea01..24af20cf2 100644 --- a/logic/BaseInstance.cpp +++ b/logic/BaseInstance.cpp @@ -37,7 +37,6 @@ BaseInstance::BaseInstance(BaseInstancePrivate *d_in, const QString &rootDir, I_D(BaseInstance); d->m_settings = settings_obj; d->m_rootDir = rootDir; - d->m_flags = 0; settings().registerSetting("name", "Unnamed Instance"); settings().registerSetting("iconKey", "default"); @@ -147,13 +146,13 @@ SettingsObject &BaseInstance::settings() const return *d->m_settings; } -BaseInstance::InstanceFlags BaseInstance::flags() const +QSet BaseInstance::flags() const { I_D(const BaseInstance); - return InstanceFlags(d->m_flags); + return QSet(d->m_flags); } -void BaseInstance::setFlags(const BaseInstance::InstanceFlags flags) +void BaseInstance::setFlags(const QSet &flags) { I_D(BaseInstance); if (flags != d->m_flags) @@ -166,7 +165,7 @@ void BaseInstance::setFlags(const BaseInstance::InstanceFlags flags) bool BaseInstance::canLaunch() const { - return !(flags() & VersionBrokenFlag); + return !flags().contains(VersionBrokenFlag); } QString BaseInstance::baseJar() const diff --git a/logic/BaseInstance.h b/logic/BaseInstance.h index 27f939bcf..443b0eaa6 100644 --- a/logic/BaseInstance.h +++ b/logic/BaseInstance.h @@ -17,6 +17,7 @@ #include #include +#include #include @@ -184,9 +185,8 @@ public: NoFlags = 0x00, VersionBrokenFlag = 0x01 }; - Q_DECLARE_FLAGS(InstanceFlags, InstanceFlag) - InstanceFlags flags() const; - void setFlags(const BaseInstance::InstanceFlags flags); + QSet flags() const; + void setFlags(const QSet &flags); bool canLaunch() const; @@ -216,4 +216,4 @@ protected: // pointer for lazy people typedef std::shared_ptr InstancePtr; -Q_DECLARE_OPERATORS_FOR_FLAGS(BaseInstance::InstanceFlags) +Q_DECLARE_METATYPE(BaseInstance::InstanceFlag) diff --git a/logic/BaseInstance_p.h b/logic/BaseInstance_p.h index 73eebec73..8cf3b27d0 100644 --- a/logic/BaseInstance_p.h +++ b/logic/BaseInstance_p.h @@ -14,10 +14,13 @@ */ #pragma once + #include +#include + #include -class BaseInstance; +#include "BaseInstance.h" #define I_D(Class) Class##Private *const d = (Class##Private * const)inst_d.get() @@ -26,5 +29,5 @@ struct BaseInstancePrivate QString m_rootDir; QString m_group; SettingsObject *m_settings; - int m_flags; + QSet m_flags; }; diff --git a/logic/LegacyFTBInstance.cpp b/logic/LegacyFTBInstance.cpp index 23cb259d4..3c3356c98 100644 --- a/logic/LegacyFTBInstance.cpp +++ b/logic/LegacyFTBInstance.cpp @@ -7,7 +7,7 @@ LegacyFTBInstance::LegacyFTBInstance(const QString &rootDir, SettingsObject *set QString LegacyFTBInstance::getStatusbarDescription() { - if (flags() & VersionBrokenFlag) + if (flags().contains(VersionBrokenFlag)) { return "Legacy FTB: " + intendedVersionId() + " (broken)"; } diff --git a/logic/LegacyInstance.cpp b/logic/LegacyInstance.cpp index 3b9181e0f..4f2dfd9be 100644 --- a/logic/LegacyInstance.cpp +++ b/logic/LegacyInstance.cpp @@ -268,7 +268,7 @@ QString LegacyInstance::defaultCustomBaseJar() const bool LegacyInstance::menuActionEnabled(QString action_name) const { - if (flags() & VersionBrokenFlag) + if (flags().contains(VersionBrokenFlag)) { return false; } @@ -281,7 +281,7 @@ bool LegacyInstance::menuActionEnabled(QString action_name) const QString LegacyInstance::getStatusbarDescription() { - if (flags() & VersionBrokenFlag) + if (flags().contains(VersionBrokenFlag)) { return "Legacy : " + intendedVersionId() + " (broken)"; } diff --git a/logic/NostalgiaInstance.cpp b/logic/NostalgiaInstance.cpp index 96ce4cc72..52820725d 100644 --- a/logic/NostalgiaInstance.cpp +++ b/logic/NostalgiaInstance.cpp @@ -23,7 +23,7 @@ NostalgiaInstance::NostalgiaInstance(const QString &rootDir, SettingsObject *set QString NostalgiaInstance::getStatusbarDescription() { - if (flags() & VersionBrokenFlag) + if (flags().contains(VersionBrokenFlag)) { return "Nostalgia : " + intendedVersionId() + " (broken)"; } diff --git a/logic/OneSixFTBInstance.cpp b/logic/OneSixFTBInstance.cpp index 91efce8e1..07b123b6d 100644 --- a/logic/OneSixFTBInstance.cpp +++ b/logic/OneSixFTBInstance.cpp @@ -182,7 +182,7 @@ bool OneSixFTBInstance::providesVersionFile() const QString OneSixFTBInstance::getStatusbarDescription() { - if (flags() & VersionBrokenFlag) + if (flags().contains(VersionBrokenFlag)) { return "OneSix FTB: " + intendedVersionId() + " (broken)"; } diff --git a/logic/OneSixInstance.cpp b/logic/OneSixInstance.cpp index 10411c560..148fbc09e 100644 --- a/logic/OneSixInstance.cpp +++ b/logic/OneSixInstance.cpp @@ -327,12 +327,12 @@ bool OneSixInstance::reloadVersion(QWidget *widgetParent) } if (ret) { - setFlags(flags() & ~VersionBrokenFlag); + d->m_flags.remove(VersionBrokenFlag); emit versionReloaded(); } else { - setFlags(flags() | VersionBrokenFlag); + d->m_flags.insert(VersionBrokenFlag); } return ret; } @@ -369,7 +369,7 @@ QString OneSixInstance::defaultCustomBaseJar() const bool OneSixInstance::menuActionEnabled(QString action_name) const { - if (flags() & VersionBrokenFlag) + if (flags().contains(VersionBrokenFlag)) { return false; } @@ -387,7 +387,7 @@ QString OneSixInstance::getStatusbarDescription() { descr += " (custom)"; } - if (flags() & VersionBrokenFlag) + if (flags().contains(VersionBrokenFlag)) { descr += " (broken)"; } diff --git a/resources/instances/broken.png b/resources/instances/broken.png new file mode 100644 index 0000000000000000000000000000000000000000..9be55691366ae61b828b814489bb7ec91f21ba9c GIT binary patch literal 1589 zcmaJ>drT8|9KZM=zy?yL4m2C*f$k-}N8dLJYkO3>SR`$om2SduJ!r+=mAk{%mc%D2 z_+-l_1lh|uA2G&ly0O7zyxhczB$AM!=x`zuV%#JVv@Yz5fc&v|$=&bu`Fy_5-&N#f zuZW3W6b%4Cj46w-h+|y%jf@b#Nh9N=I3x<0cEQRP3OD*Lu zkxm1E*>1PZF4)a0afXS)Xt_Vgo8ckRO!%{^=D!+*lNPjBBCr>F5G*5AEui$1GFsw)x zu%&_)5`( z`n+wEmxe7g&z5qOSjEER8K$0ZC=8s80XLIeF)dcnNN(Wii3774Cs?Y~LoU2ACoeD8(G%|%sBO_3hFsd;fW>jjFI#ivB5=vx>YhrkTWGH%y>wd0M#vLHgNBgFHARY#Ck-n)9dvH zqY+hMs6q+Bq8o6yKW6mH)Rx$U;pueui;L;|Lo;H!Iq`NZ>^YtZ0J92AgwE#g-D}Cq zvXb*NMjL)0*2h(C-TU$I$J}?J&2tkUy!JD1A(9S;d(NO1TU9z^W8p!=HMQf~& z9bY$mn6K+uf3UBwJTDmhynDD*qHFv{trMG%xSGoJkVZnCZWQAclp`2bDh~B z^;KbYTZQdJ-=!Sg>7-04m;VmxKDknP`n@kI zTYh{$R^N}PgMsupt^Fl?8zr-ztlT20iAo$Zv<(TB!}jG1$Kv-4)Gn|&-f~ICY9m+2 zuUb}mTmF$fX7)}~20GR@IKmvW;8E?8K8m_wTXrPRHb3j=)yECx<=~y2D?cr})V~FP z^GM$wSMGeY{?&b0psK5*BmPmIN>%fFLRqfE5xB#B(AWFNQ0w^3-LKs|du{8wqb1A!f(p4%^_-@l(R z*!0SxK*j4dY2^XtR8`mAb zDR0;H(0LeMWnC)|Ua!{cOEM|=FDl*J@NYGi-0MHvH180OcgDmojZSGommL3Xv8Q!h znA>~k+qL72X5Q|p8R@i;K7m-SNi4`5WoRc6n@#W|6%w?ZpzFiPV4ix F{Ri2LU2XsX literal 0 HcmV?d00001 diff --git a/resources/instances/instances.qrc b/resources/instances/instances.qrc index ec3cdf214..22e2936d3 100644 --- a/resources/instances/instances.qrc +++ b/resources/instances/instances.qrc @@ -32,4 +32,11 @@ squarecreeper128.png steve128.png + + enderman.png + herobrine.png + kitten.png + broken.png + derp.png + diff --git a/resources/instances/kitten.png b/resources/instances/kitten.png new file mode 100644 index 0000000000000000000000000000000000000000..f9999b06138f1b8aa946ba4d23e32a287492962e GIT binary patch literal 9107 zcmeI1X*kq*0LRU^W|$d+Ovo{E=DtQF?XD3K@r>jwxuOhZGtr^7Ge{GXGn8wF9(OdT zcF9$YJ0?UHlX7;aRq2@ht9{y@&2D*~&A$21iGSCG zbn+~|xUY(LZE(#S;pSrZ-R?YUSZl*gOjJ@*8lq7M zdI})~9c#SS$c?DCisSU*!jQaX{6T%Xz;vGsrY} zS&$&S={keZ%F1UAbOf+(H1x8ed1lRR)q_QRc~EwDJ!icC?j&pK!TqAqCp}I55CNz( z(P=BE;n>4EuVvWgM51A=zC-96iS~7RIY{z=jR@Ia!6`n@C`qYJ-(-&H(YS5MG6`4F4~K6W z+8kA1;*8<+E&MJszD5yCYp9vu>CQSS!m?Ctih?mM%iZIQp{F^+f_waHH`I;|6i1#e z)N{vRr-%A0oy1MM7`mA)t%9LDta1kCPhOH2CL12gkPg64xhNnZ^9`P4-q}>y$fp*q zIbK$3uu&azm+3nvu+eJXQ3@b6AT=O0VAiZ$)&R%SUndkFctU|E)Ur<~kQ%VpEWg)) z)PU50)PNgmB{ozPP;&ld{sY?|FaRIt|A*}l41Zw$f6ev>9{ykSruY-@mwh7b!?G9o zUzdF*B}HOx71pCBDE&>_v#J2>HRyv;i6VLjr8yR@v8yWmfKBJNSY!gt_z>Xtci3M z#2C=T$J9y>vKXu++M9mJM2cibxaw;wGaXywkPKYpD({}|+8V_|nzsEW+cUnQO`4++ zDr>fnj6V>a6^6vXM6oaHvK$Y!;A9<+KzE(HxU=!)ESg7dA?WGV>_|gZRLcGw{caBx zRXhoKxc{=N61C9JUefN6asg{3n=Hj(C=SJpDM=bA>Kc$s0&`2uA$F&*#xkUSXj zC~`e1t~Jp^JOP5?;&rDz33{oT?o5MM0_W9IQNiuUG8_t+@dldgZMmM*-Yk(IIb}D5 z8iLNCSp!aKmXBXqgOO=nt$s5@jvmVIpPYMB2KVe#b#I7VmsxnD zwIs%X!aH_2?1j}?3!31IpM(GeS)r?MX%^VA^#P}3wdj<5+s$-68qHh)rxg0Vs&t@Y z#Bi6q@Q<^{j&ujcilWV7;;tpy!31p_C@l}|7p@clok!U4MI#Nxm&Q=%G-L zKEQ!TAdIFtk?80pY|;|+eJVo1B>c>Af=T$Tk`P<~-~w3w0ss?ixwkZ6f_~bc508SR!oB#j- literal 0 HcmV?d00001 From ad9b16bd3d6a71b4cdf1763d166bc9cc633e147c Mon Sep 17 00:00:00 2001 From: Jan Dalheimer Date: Fri, 14 Mar 2014 22:01:27 +0100 Subject: [PATCH 2/2] Nicer icons --- resources/instances/broken.png | Bin 1589 -> 1139 bytes resources/instances/instances.qrc | 8 ++++++-- resources/instances/kitten.png | Bin 9107 -> 1605 bytes 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/resources/instances/broken.png b/resources/instances/broken.png index 9be55691366ae61b828b814489bb7ec91f21ba9c..7a80a76e53c3fd4e6a407e18c569f6cef05b25b7 100644 GIT binary patch literal 1139 zcmV-(1dRKMP)q0O%v~H_;>WgX8+#S*7o(c(9k%E7Y+;zF~zMFV~EYj(#No^!NAYE0xMOPesi))*<)g_gTP;v9U36fLI3Tm5rPqF=3Yx zH@~8yLi4`>*s+*I_#O8#V0?W1ze#j`eN8(%JCk5f%EBLG0WY2e*k@oc82*Ziiju{} z#rfGq%*n#fp5sK;T?Cc>g zFRx*1YwM)|(An9UUsqShNrV<1A0J!$`ucu=MSpg5bSTjn9PeKcz!HAplMV6&V?+!_|lvu)5;KB=l)M0LjAdBLJKQHTV+( zfJjA0N9$0ZpEe5U(J z;Q;VoAiul2t4398Kgs@62ESikUOud^ufGQ8Mlt88{R7$drT8|9KZM=zy?yL4m2C*f$k-}N8dLJYkO3>SR`$om2SduJ!r+=mAk{%mc%D2 z_+-l_1lh|uA2G&ly0O7zyxhczB$AM!=x`zuV%#JVv@Yz5fc&v|$=&bu`Fy_5-&N#f zuZW3W6b%4Cj46w-h+|y%jf@b#Nh9N=I3x<0cEQRP3OD*Lu zkxm1E*>1PZF4)a0afXS)Xt_Vgo8ckRO!%{^=D!+*lNPjBBCr>F5G*5AEui$1GFsw)x zu%&_)5`( z`n+wEmxe7g&z5qOSjEER8K$0ZC=8s80XLIeF)dcnNN(Wii3774Cs?Y~LoU2ACoeD8(G%|%sBO_3hFsd;fW>jjFI#ivB5=vx>YhrkTWGH%y>wd0M#vLHgNBgFHARY#Ck-n)9dvH zqY+hMs6q+Bq8o6yKW6mH)Rx$U;pueui;L;|Lo;H!Iq`NZ>^YtZ0J92AgwE#g-D}Cq zvXb*NMjL)0*2h(C-TU$I$J}?J&2tkUy!JD1A(9S;d(NO1TU9z^W8p!=HMQf~& z9bY$mn6K+uf3UBwJTDmhynDD*qHFv{trMG%xSGoJkVZnCZWQAclp`2bDh~B z^;KbYTZQdJ-=!Sg>7-04m;VmxKDknP`n@kI zTYh{$R^N}PgMsupt^Fl?8zr-ztlT20iAo$Zv<(TB!}jG1$Kv-4)Gn|&-f~ICY9m+2 zuUb}mTmF$fX7)}~20GR@IKmvW;8E?8K8m_wTXrPRHb3j=)yECx<=~y2D?cr})V~FP z^GM$wSMGeY{?&b0psK5*BmPmIN>%fFLRqfE5xB#B(AWFNQ0w^3-LKs|du{8wqb1A!f(p4%^_-@l(R z*!0SxK*j4dY2^XtR8`mAb zDR0;H(0LeMWnC)|Ua!{cOEM|=FDl*J@NYGi-0MHvH180OcgDmojZSGommL3Xv8Q!h znA>~k+qL72X5Q|p8R@i;K7m-SNi4`5WoRc6n@#W|6%w?ZpzFiPV4ix F{Ri2LU2XsX diff --git a/resources/instances/instances.qrc b/resources/instances/instances.qrc index 22e2936d3..5124b846d 100644 --- a/resources/instances/instances.qrc +++ b/resources/instances/instances.qrc @@ -33,10 +33,14 @@ steve128.png + enderman.png herobrine.png - kitten.png - broken.png derp.png + + + kitten.png + + broken.png diff --git a/resources/instances/kitten.png b/resources/instances/kitten.png index f9999b06138f1b8aa946ba4d23e32a287492962e..d17661ce5775bfe1493b7ed23d8632174ff431cc 100644 GIT binary patch literal 1605 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