aboutsummaryrefslogtreecommitdiff
path: root/launcher/minecraft/mod
diff options
context:
space:
mode:
authorRachel Powers <508861+Ryex@users.noreply.github.com>2023-05-04 23:45:24 -0700
committerRachel Powers <508861+Ryex@users.noreply.github.com>2023-05-04 23:45:24 -0700
commitd384d991fad80cdadf6486d61e5c06a692a0031d (patch)
tree3adc89354b54596c8da70a2878b5641fa25d63ed /launcher/minecraft/mod
parent9913080a829acb4ca921c3a68e0caefad0ebcaa1 (diff)
downloadPrismLauncher-d384d991fad80cdadf6486d61e5c06a692a0031d.tar.gz
PrismLauncher-d384d991fad80cdadf6486d61e5c06a692a0031d.tar.bz2
PrismLauncher-d384d991fad80cdadf6486d61e5c06a692a0031d.zip
feat(texturepackPage): icon column
Signed-off-by: Rachel Powers <508861+Ryex@users.noreply.github.com>
Diffstat (limited to 'launcher/minecraft/mod')
-rw-r--r--launcher/minecraft/mod/TexturePack.cpp25
-rw-r--r--launcher/minecraft/mod/TexturePack.h6
-rw-r--r--launcher/minecraft/mod/TexturePackFolderModel.cpp102
-rw-r--r--launcher/minecraft/mod/TexturePackFolderModel.h20
-rw-r--r--launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp67
-rw-r--r--launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h5
6 files changed, 211 insertions, 14 deletions
diff --git a/launcher/minecraft/mod/TexturePack.cpp b/launcher/minecraft/mod/TexturePack.cpp
index 99d55584..8ff1e852 100644
--- a/launcher/minecraft/mod/TexturePack.cpp
+++ b/launcher/minecraft/mod/TexturePack.cpp
@@ -23,6 +23,8 @@
#include <QMap>
#include <QRegularExpression>
+#include "MTPixmapCache.h"
+
#include "minecraft/mod/tasks/LocalTexturePackParseTask.h"
void TexturePack::setDescription(QString new_description)
@@ -32,34 +34,41 @@ void TexturePack::setDescription(QString new_description)
m_description = new_description;
}
-void TexturePack::setImage(QImage new_image)
+void TexturePack::setImage(QImage new_image) const
{
QMutexLocker locker(&m_data_lock);
Q_ASSERT(!new_image.isNull());
if (m_pack_image_cache_key.key.isValid())
- QPixmapCache::remove(m_pack_image_cache_key.key);
+ PixmapCache::remove(m_pack_image_cache_key.key);
+
+ // scale the image to avoid flooding the pixmapcache
+ auto pixmap = QPixmap::fromImage(new_image.scaled(QSize(128, 128), Qt::AspectRatioMode::KeepAspectRatioByExpanding));
- m_pack_image_cache_key.key = QPixmapCache::insert(QPixmap::fromImage(new_image));
+ m_pack_image_cache_key.key = PixmapCache::insert(pixmap);
m_pack_image_cache_key.was_ever_used = true;
}
-QPixmap TexturePack::image(QSize size)
+QPixmap TexturePack::image(QSize size, Qt::AspectRatioMode mode) const
{
QPixmap cached_image;
- if (QPixmapCache::find(m_pack_image_cache_key.key, &cached_image)) {
+ if (PixmapCache::find(m_pack_image_cache_key.key, &cached_image)) {
if (size.isNull())
return cached_image;
- return cached_image.scaled(size);
+ return cached_image.scaled(size, mode);
}
// No valid image we can get
- if (!m_pack_image_cache_key.was_ever_used)
+ if (!m_pack_image_cache_key.was_ever_used) {
return {};
+ } else {
+ qDebug() << "Texture Pack" << name() << "Had it's image evicted from the cache. reloading...";
+ PixmapCache::markCacheMissByEviciton();
+ }
// Imaged got evicted from the cache. Re-process it and retry.
- TexturePackUtils::process(*this);
+ TexturePackUtils::processPackPNG(*this);
return image(size);
}
diff --git a/launcher/minecraft/mod/TexturePack.h b/launcher/minecraft/mod/TexturePack.h
index 81bd5c69..57700565 100644
--- a/launcher/minecraft/mod/TexturePack.h
+++ b/launcher/minecraft/mod/TexturePack.h
@@ -40,13 +40,13 @@ class TexturePack : public Resource {
[[nodiscard]] QString description() const { return m_description; }
/** Gets the image of the texture pack, converted to a QPixmap for drawing, and scaled to size. */
- [[nodiscard]] QPixmap image(QSize size);
+ [[nodiscard]] QPixmap image(QSize size, Qt::AspectRatioMode mode = Qt::AspectRatioMode::IgnoreAspectRatio) const;
/** Thread-safe. */
void setDescription(QString new_description);
/** Thread-safe. */
- void setImage(QImage new_image);
+ void setImage(QImage new_image) const;
bool valid() const override;
@@ -65,5 +65,5 @@ class TexturePack : public Resource {
struct {
QPixmapCache::Key key;
bool was_ever_used = false;
- } m_pack_image_cache_key;
+ } mutable m_pack_image_cache_key;
};
diff --git a/launcher/minecraft/mod/TexturePackFolderModel.cpp b/launcher/minecraft/mod/TexturePackFolderModel.cpp
index 1e218537..dd93a469 100644
--- a/launcher/minecraft/mod/TexturePackFolderModel.cpp
+++ b/launcher/minecraft/mod/TexturePackFolderModel.cpp
@@ -33,6 +33,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <QCoreApplication>
+
+#include "Application.h"
#include "TexturePackFolderModel.h"
@@ -41,7 +44,9 @@
TexturePackFolderModel::TexturePackFolderModel(const QString& dir, std::shared_ptr<const BaseInstance> instance)
: ResourceFolderModel(QDir(dir), instance)
-{}
+{
+ m_column_sort_keys = { SortType::ENABLED, SortType::NAME, SortType::DATE, SortType::NAME };
+}
Task* TexturePackFolderModel::createUpdateTask()
{
@@ -52,3 +57,98 @@ Task* TexturePackFolderModel::createParseTask(Resource& resource)
{
return new LocalTexturePackParseTask(m_next_resolution_ticket, static_cast<TexturePack&>(resource));
}
+
+
+QVariant TexturePackFolderModel::data(const QModelIndex& index, int role) const
+{
+ if (!validateIndex(index))
+ return {};
+
+ int row = index.row();
+ int column = index.column();
+
+ switch (role) {
+ case Qt::DisplayRole:
+ switch (column) {
+ case NameColumn:
+ return m_resources[row]->name();
+ case DateColumn:
+ return m_resources[row]->dateTimeChanged();
+ default:
+ return {};
+ }
+ case Qt::ToolTipRole:
+ if (column == NameColumn) {
+ if (at(row)->isSymLinkUnder(instDirPath())) {
+ return m_resources[row]->internal_id() +
+ tr("\nWarning: This resource is symbolically linked from elsewhere. Editing it will also change the original."
+ "\nCanonical Path: %1")
+ .arg(at(row)->fileinfo().canonicalFilePath());;
+ }
+ if (at(row)->isMoreThanOneHardLink()) {
+ return m_resources[row]->internal_id() +
+ tr("\nWarning: This resource is hard linked elsewhere. Editing it will also change the original.");
+ }
+ }
+
+ return m_resources[row]->internal_id();
+ case Qt::DecorationRole: {
+ if (column == NameColumn && (at(row)->isSymLinkUnder(instDirPath()) || at(row)->isMoreThanOneHardLink()))
+ return APPLICATION->getThemedIcon("status-yellow");
+ if (column == ImageColumn) {
+ return at(row)->image(QSize(64, 64), Qt::AspectRatioMode::KeepAspectRatioByExpanding);
+ }
+ return {};
+ }
+ case Qt::CheckStateRole:
+ switch (column) {
+ case ActiveColumn:
+ return m_resources[row]->enabled() ? Qt::Checked : Qt::Unchecked;
+ default:
+ return {};
+ }
+ default:
+ return {};
+ }
+}
+
+QVariant TexturePackFolderModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ switch (role) {
+ case Qt::DisplayRole:
+ switch (section) {
+ case NameColumn:
+ return tr("Name");
+ case DateColumn:
+ return tr("Last modified");
+ case ImageColumn:
+ return tr("Image");
+ default:
+ return {};
+ }
+ case Qt::ToolTipRole: {
+ switch (section) {
+ case ActiveColumn:
+ //: Here, resource is a generic term for external resources, like Mods, Resource Packs, Shader Packs, etc.
+ return tr("Is the resource enabled?");
+ case NameColumn:
+ //: Here, resource is a generic term for external resources, like Mods, Resource Packs, Shader Packs, etc.
+ return tr("The name of the resource.");
+ case DateColumn:
+ //: Here, resource is a generic term for external resources, like Mods, Resource Packs, Shader Packs, etc.
+ return tr("The date and time this resource was last changed (or added).");
+ default:
+ return {};
+ }
+ }
+ default:
+ break;
+ }
+
+ return {};
+}
+
+int TexturePackFolderModel::columnCount(const QModelIndex& parent) const
+{
+ return parent.isValid() ? 0 : NUM_COLUMNS;
+} \ No newline at end of file
diff --git a/launcher/minecraft/mod/TexturePackFolderModel.h b/launcher/minecraft/mod/TexturePackFolderModel.h
index 246997bd..4467691a 100644
--- a/launcher/minecraft/mod/TexturePackFolderModel.h
+++ b/launcher/minecraft/mod/TexturePackFolderModel.h
@@ -38,12 +38,32 @@
#include "ResourceFolderModel.h"
+#include "TexturePack.h"
+
class TexturePackFolderModel : public ResourceFolderModel
{
Q_OBJECT
public:
+
+ enum Columns
+ {
+ ActiveColumn = 0,
+ NameColumn,
+ DateColumn,
+ ImageColumn,
+ NUM_COLUMNS
+ };
+
explicit TexturePackFolderModel(const QString &dir, std::shared_ptr<const BaseInstance> instance);
+
+ [[nodiscard]] QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+ [[nodiscard]] QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+ [[nodiscard]] int columnCount(const QModelIndex &parent) const override;
+
[[nodiscard]] Task* createUpdateTask() override;
[[nodiscard]] Task* createParseTask(Resource&) override;
+
+ RESOURCE_HELPERS(TexturePack)
};
diff --git a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp
index 38f1d7c1..a72e8115 100644
--- a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp
+++ b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.cpp
@@ -131,6 +131,7 @@ bool processZIP(TexturePack& pack, ProcessingLevel level)
bool packPNG_result = TexturePackUtils::processPackPNG(pack, std::move(data));
file.close();
+ zip.close();
if (!packPNG_result) {
return false;
}
@@ -147,7 +148,7 @@ bool processPackTXT(TexturePack& pack, QByteArray&& raw_data)
return true;
}
-bool processPackPNG(TexturePack& pack, QByteArray&& raw_data)
+bool processPackPNG(const TexturePack& pack, QByteArray&& raw_data)
{
auto img = QImage::fromData(raw_data);
if (!img.isNull()) {
@@ -159,6 +160,70 @@ bool processPackPNG(TexturePack& pack, QByteArray&& raw_data)
return true;
}
+bool processPackPNG(const TexturePack& pack)
+{
+ auto png_invalid = [&pack]() {
+ qWarning() << "Texture pack at" << pack.fileinfo().filePath() << "does not have a valid pack.png";
+ return false;
+ };
+
+ switch (pack.type()) {
+ case ResourceType::FOLDER:
+ {
+ QFileInfo image_file_info(FS::PathCombine(pack.fileinfo().filePath(), "pack.png"));
+ if (image_file_info.exists() && image_file_info.isFile()) {
+ QFile pack_png_file(image_file_info.filePath());
+ if (!pack_png_file.open(QIODevice::ReadOnly))
+ return png_invalid(); // can't open pack.png file
+
+ auto data = pack_png_file.readAll();
+
+ bool pack_png_result = TexturePackUtils::processPackPNG(pack, std::move(data));
+
+ pack_png_file.close();
+ if (!pack_png_result) {
+ return png_invalid(); // pack.png invalid
+ }
+ } else {
+ return png_invalid(); // pack.png does not exists or is not a valid file.
+ }
+ }
+ case ResourceType::ZIPFILE:
+ {
+ Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
+
+ QuaZip zip(pack.fileinfo().filePath());
+ if (!zip.open(QuaZip::mdUnzip))
+ return false; // can't open zip file
+
+ QuaZipFile file(&zip);
+ if (zip.setCurrentFile("pack.png")) {
+ if (!file.open(QIODevice::ReadOnly)) {
+ qCritical() << "Failed to open file in zip.";
+ zip.close();
+ return png_invalid();
+ }
+
+ auto data = file.readAll();
+
+ bool pack_png_result = TexturePackUtils::processPackPNG(pack, std::move(data));
+
+ file.close();
+ if (!pack_png_result) {
+ zip.close();
+ return png_invalid(); // pack.png invalid
+ }
+ } else {
+ zip.close();
+ return png_invalid(); // could not set pack.mcmeta as current file.
+ }
+ }
+ default:
+ qWarning() << "Invalid type for resource pack parse task!";
+ return false;
+ }
+}
+
bool validate(QFileInfo file)
{
TexturePack rp{ file };
diff --git a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h
index 1589f8cb..6b91565a 100644
--- a/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h
+++ b/launcher/minecraft/mod/tasks/LocalTexturePackParseTask.h
@@ -36,7 +36,10 @@ bool processZIP(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full
bool processFolder(TexturePack& pack, ProcessingLevel level = ProcessingLevel::Full);
bool processPackTXT(TexturePack& pack, QByteArray&& raw_data);
-bool processPackPNG(TexturePack& pack, QByteArray&& raw_data);
+bool processPackPNG(const TexturePack& pack, QByteArray&& raw_data);
+
+/// processes ONLY the pack.png (rest of the pack may be invalid)
+bool processPackPNG(const TexturePack& pack);
/** Checks whether a file is valid as a texture pack or not. */
bool validate(QFileInfo file);