From afa1a5e93228350ea5689b39655046b49a0133a5 Mon Sep 17 00:00:00 2001 From: flow Date: Sun, 28 Aug 2022 22:31:48 -0300 Subject: feat: modify InfoFrame and ResourcePackPage to show ResourcePack info Signed-off-by: flow --- launcher/ui/pages/instance/ResourcePackPage.h | 11 +++ launcher/ui/widgets/InfoFrame.cpp | 104 ++++++++++++++++++++++---- launcher/ui/widgets/InfoFrame.h | 1 + 3 files changed, 101 insertions(+), 15 deletions(-) (limited to 'launcher/ui') diff --git a/launcher/ui/pages/instance/ResourcePackPage.h b/launcher/ui/pages/instance/ResourcePackPage.h index 2eefc3d3..9633e3b4 100644 --- a/launcher/ui/pages/instance/ResourcePackPage.h +++ b/launcher/ui/pages/instance/ResourcePackPage.h @@ -61,4 +61,15 @@ public: return !m_instance->traits().contains("no-texturepacks") && !m_instance->traits().contains("texturepacks"); } + + public slots: + bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override + { + auto sourceCurrent = m_filterModel->mapToSource(current); + int row = sourceCurrent.row(); + auto& rp = static_cast(m_model->at(row)); + ui->frame->updateWithResourcePack(rp); + + return true; + } }; diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 821e61a7..69d77603 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -1,17 +1,37 @@ -/* Copyright 2013-2021 MultiMC Contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// SPDX-License-Identifier: GPL-3.0-only +/* +* PolyMC - Minecraft Launcher +* Copyright (c) 2022 flowln +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, version 3. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* This file incorporates work covered by the following copyright and +* permission notice: +* +* Copyright 2013-2021 MultiMC Contributors +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ #include @@ -74,6 +94,60 @@ void InfoFrame::updateWithResource(const Resource& resource) setName(resource.name()); } +// https://www.sportskeeda.com/minecraft-wiki/color-codes +static const QMap s_value_to_color = { + {'0', "#000000"}, {'1', "#0000AA"}, {'2', "#00AA00"}, {'3', "#00AAAA"}, {'4', "#AA0000"}, + {'5', "#AA00AA"}, {'6', "#FFAA00"}, {'7', "#AAAAAA"}, {'8', "#555555"}, {'9', "#5555FF"}, + {'a', "#55FF55"}, {'b', "#55FFFF"}, {'c', "#FF5555"}, {'d', "#FF55FF"}, {'e', "#FFFF55"}, + {'f', "#FFFFFF"} +}; + +void InfoFrame::updateWithResourcePack(const ResourcePack& resource_pack) +{ + setName(resource_pack.name()); + + // We have to manually set the colors for use. + // + // A color is set using §x, with x = a hex number from 0 to f. + // + // We traverse the description and, when one of those is found, we create + // a span element with that color set. + // + // TODO: Make the same logic for font formatting too. + // TODO: Wrap links inside tags + + auto description = resource_pack.description(); + + QString description_parsed(""); + bool in_div = false; + + auto desc_it = description.constBegin(); + while (desc_it != description.constEnd()) { + if (*desc_it == u'§') { + if (in_div) + description_parsed += ""; + + auto const& num = *(++desc_it); + description_parsed += QString("").arg(s_value_to_color.constFind(num).value()); + + in_div = true; + + desc_it++; + } + + description_parsed += *desc_it; + desc_it++; + } + + if (in_div) + description_parsed += ""; + description_parsed += ""; + + description_parsed.replace("\n", "
"); + + setDescription(description_parsed); +} + void InfoFrame::clear() { setName(); @@ -146,7 +220,7 @@ void InfoFrame::setDescription(QString text) } else { - ui->descriptionLabel->setTextFormat(Qt::TextFormat::PlainText); + ui->descriptionLabel->setTextFormat(Qt::TextFormat::AutoText); labeltext.append(finaltext); } ui->descriptionLabel->setText(labeltext); diff --git a/launcher/ui/widgets/InfoFrame.h b/launcher/ui/widgets/InfoFrame.h index d69dc232..4b6df023 100644 --- a/launcher/ui/widgets/InfoFrame.h +++ b/launcher/ui/widgets/InfoFrame.h @@ -39,6 +39,7 @@ class InfoFrame : public QFrame { void updateWithMod(Mod const& m); void updateWithResource(Resource const& resource); + void updateWithResourcePack(ResourcePack const& rp); public slots: void descriptionEllipsisHandler(QString link); -- cgit From dd9e30b24ab20c6e559618f435b141383e0d0fcd Mon Sep 17 00:00:00 2001 From: flow Date: Mon, 29 Aug 2022 09:14:15 -0300 Subject: feat: add resource icon to InfoFrame Signed-off-by: flow --- launcher/ui/widgets/InfoFrame.cpp | 15 +++++++++++++++ launcher/ui/widgets/InfoFrame.h | 1 + launcher/ui/widgets/InfoFrame.ui | 34 ++++++++++++++++++++++++++++------ 3 files changed, 44 insertions(+), 6 deletions(-) (limited to 'launcher/ui') diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 69d77603..97d0ba37 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -87,11 +87,14 @@ void InfoFrame::updateWithMod(Mod const& m) { setDescription(m.description()); } + + setImage(); } void InfoFrame::updateWithResource(const Resource& resource) { setName(resource.name()); + setImage(); } // https://www.sportskeeda.com/minecraft-wiki/color-codes @@ -146,12 +149,14 @@ void InfoFrame::updateWithResourcePack(const ResourcePack& resource_pack) description_parsed.replace("\n", "
"); setDescription(description_parsed); + setImage(resource_pack.image({64, 64})); } void InfoFrame::clear() { setName(); setDescription(); + setImage(); } void InfoFrame::updateHiddenState() @@ -226,6 +231,16 @@ void InfoFrame::setDescription(QString text) ui->descriptionLabel->setText(labeltext); } +void InfoFrame::setImage(QPixmap img) +{ + if (img.isNull()) { + ui->iconLabel->setHidden(true); + } else { + ui->iconLabel->setHidden(false); + ui->iconLabel->setPixmap(img); + } +} + void InfoFrame::descriptionEllipsisHandler(QString link) { if(!m_current_box) diff --git a/launcher/ui/widgets/InfoFrame.h b/launcher/ui/widgets/InfoFrame.h index 4b6df023..d914aa0c 100644 --- a/launcher/ui/widgets/InfoFrame.h +++ b/launcher/ui/widgets/InfoFrame.h @@ -34,6 +34,7 @@ class InfoFrame : public QFrame { void setName(QString text = {}); void setDescription(QString text = {}); + void setImage(QPixmap img = {}); void clear(); diff --git a/launcher/ui/widgets/InfoFrame.ui b/launcher/ui/widgets/InfoFrame.ui index 0d3772d7..9e407ce9 100644 --- a/launcher/ui/widgets/InfoFrame.ui +++ b/launcher/ui/widgets/InfoFrame.ui @@ -22,10 +22,7 @@ 120 - - - 6 - + 0 @@ -38,7 +35,7 @@ 0 - + @@ -60,7 +57,7 @@ - + @@ -85,6 +82,31 @@ + + + + + 0 + 0 + + + + + 64 + 64 + + + + + + + false + + + 0 + + + -- cgit From 3b13e692d29c96f99b2c153dd2c7933070eb8479 Mon Sep 17 00:00:00 2001 From: flow Date: Tue, 30 Aug 2022 18:06:13 -0300 Subject: feat: move resource pack images to QPixmapCache This takes care of evicting entries when the cache gets too big for us, so we can add new entries without much worries. Signed-off-by: flow --- launcher/minecraft/mod/ResourcePack.cpp | 26 +++++++++++++++++++++- launcher/minecraft/mod/ResourcePack.h | 15 ++++++++----- .../mod/tasks/LocalResourcePackParseTask.cpp | 2 ++ launcher/ui/widgets/InfoFrame.cpp | 2 +- launcher/ui/widgets/InfoFrame.h | 2 +- 5 files changed, 39 insertions(+), 8 deletions(-) (limited to 'launcher/ui') diff --git a/launcher/minecraft/mod/ResourcePack.cpp b/launcher/minecraft/mod/ResourcePack.cpp index 77bd98aa..cc8d23ce 100644 --- a/launcher/minecraft/mod/ResourcePack.cpp +++ b/launcher/minecraft/mod/ResourcePack.cpp @@ -6,6 +6,8 @@ #include "Version.h" +#include "minecraft/mod/tasks/LocalResourcePackParseTask.h" + // Values taken from: // https://minecraft.fandom.com/wiki/Tutorials/Creating_a_resource_pack#Formatting_pack.mcmeta static const QMap> s_pack_format_versions = { @@ -41,7 +43,29 @@ void ResourcePack::setImage(QImage new_image) Q_ASSERT(!new_image.isNull()); - m_pack_image = new_image; + if (m_pack_image_cache_key.key.isValid()) + QPixmapCache::remove(m_pack_image_cache_key.key); + + m_pack_image_cache_key.key = QPixmapCache::insert(QPixmap::fromImage(new_image)); + m_pack_image_cache_key.was_ever_used = true; +} + +QPixmap ResourcePack::image(QSize size) +{ + QPixmap cached_image; + if (QPixmapCache::find(m_pack_image_cache_key.key, &cached_image)) { + if (size.isNull()) + return cached_image; + return cached_image.scaled(size); + } + + // No valid image we can get + if (!m_pack_image_cache_key.was_ever_used) + return {}; + + // Imaged got evicted from the cache. Re-process it and retry. + ResourcePackUtils::process(*this); + return image(size); } std::pair ResourcePack::compatibleVersions() const diff --git a/launcher/minecraft/mod/ResourcePack.h b/launcher/minecraft/mod/ResourcePack.h index 720fa3a0..03121908 100644 --- a/launcher/minecraft/mod/ResourcePack.h +++ b/launcher/minecraft/mod/ResourcePack.h @@ -5,6 +5,7 @@ #include #include #include +#include class Version; @@ -30,8 +31,7 @@ class ResourcePack : public Resource { [[nodiscard]] QString description() const { return m_description; } /** Gets the image of the resource pack, converted to a QPixmap for drawing, and scaled to size. */ - [[nodiscard]] QPixmap image(QSize size) const { return QPixmap::fromImage(m_pack_image).scaled(size); } - [[nodiscard]] QSize image_size() const { return m_pack_image.size(); } + [[nodiscard]] QPixmap image(QSize size); /** Thread-safe. */ void setPackFormat(int new_format_id); @@ -57,8 +57,13 @@ class ResourcePack : public Resource { */ QString m_description; - /** The resource pack's image, as per the pack.png file. - * TODO: This could probably be just a key into a static image cache. + /** The resource pack's image file cache key, for access in the QPixmapCache global instance. + * + * The 'was_ever_used' state simply identifies whether the key was never inserted on the cache (true), + * so as to tell whether a cache entry is inexistent or if it was just evicted from the cache. */ - QImage m_pack_image; + struct { + QPixmapCache::Key key; + bool was_ever_used = false; + } m_pack_image_cache_key; }; diff --git a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp index 4634e08b..4f87bc13 100644 --- a/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp +++ b/launcher/minecraft/mod/tasks/LocalResourcePackParseTask.cpp @@ -24,6 +24,8 @@ #include #include +#include + namespace ResourcePackUtils { bool process(ResourcePack& pack) diff --git a/launcher/ui/widgets/InfoFrame.cpp b/launcher/ui/widgets/InfoFrame.cpp index 97d0ba37..9e0553f8 100644 --- a/launcher/ui/widgets/InfoFrame.cpp +++ b/launcher/ui/widgets/InfoFrame.cpp @@ -105,7 +105,7 @@ static const QMap s_value_to_color = { {'f', "#FFFFFF"} }; -void InfoFrame::updateWithResourcePack(const ResourcePack& resource_pack) +void InfoFrame::updateWithResourcePack(ResourcePack& resource_pack) { setName(resource_pack.name()); diff --git a/launcher/ui/widgets/InfoFrame.h b/launcher/ui/widgets/InfoFrame.h index d914aa0c..70d15b1e 100644 --- a/launcher/ui/widgets/InfoFrame.h +++ b/launcher/ui/widgets/InfoFrame.h @@ -40,7 +40,7 @@ class InfoFrame : public QFrame { void updateWithMod(Mod const& m); void updateWithResource(Resource const& resource); - void updateWithResourcePack(ResourcePack const& rp); + void updateWithResourcePack(ResourcePack& rp); public slots: void descriptionEllipsisHandler(QString link); -- cgit From 43a7af3f44ee3520f617f46be8d239f9fe695c13 Mon Sep 17 00:00:00 2001 From: flow Date: Sat, 3 Sep 2022 13:27:27 -0300 Subject: fix: removing mods with their metadata as well Signed-off-by: flow --- launcher/ui/pages/instance/ModFolderPage.cpp | 10 ++++++++++ launcher/ui/pages/instance/ModFolderPage.h | 2 ++ 2 files changed, 12 insertions(+) (limited to 'launcher/ui') diff --git a/launcher/ui/pages/instance/ModFolderPage.cpp b/launcher/ui/pages/instance/ModFolderPage.cpp index 75b40e77..28a874c2 100644 --- a/launcher/ui/pages/instance/ModFolderPage.cpp +++ b/launcher/ui/pages/instance/ModFolderPage.cpp @@ -135,6 +135,16 @@ bool ModFolderPage::onSelectionChanged(const QModelIndex& current, const QModelI return true; } +void ModFolderPage::removeItem() +{ + + if (!m_controlsEnabled) + return; + + auto selection = m_filterModel->mapSelectionToSource(ui->treeView->selectionModel()->selection()); + m_model->deleteMods(selection.indexes()); +} + void ModFolderPage::installMods() { if (!m_controlsEnabled) diff --git a/launcher/ui/pages/instance/ModFolderPage.h b/launcher/ui/pages/instance/ModFolderPage.h index 7fc9d9a1..c9a55bde 100644 --- a/launcher/ui/pages/instance/ModFolderPage.h +++ b/launcher/ui/pages/instance/ModFolderPage.h @@ -59,6 +59,8 @@ class ModFolderPage : public ExternalResourcesPage { bool onSelectionChanged(const QModelIndex& current, const QModelIndex& previous) override; private slots: + void removeItem() override; + void installMods(); void updateMods(); -- cgit