From 3470a3df966100d4f1ea6488892ac048118a3131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Mr=C3=A1zek?= Date: Fri, 31 May 2019 21:52:58 +0200 Subject: [PATCH] NOISSUE improve icon handling while importing and exporting instances Now it handles formats other than png. --- api/gui/icons/MMCIcon.cpp | 14 +++++ api/gui/icons/MMCIcon.h | 2 + api/logic/CMakeLists.txt | 4 +- api/logic/InstanceImportTask.cpp | 6 +- api/logic/icons/IconUtils.cpp | 62 ++++++++++++++++++++ api/logic/icons/IconUtils.h | 14 +++++ application/dialogs/ExportInstanceDialog.cpp | 60 +++++++++---------- application/dialogs/IconPickerDialog.cpp | 5 +- 8 files changed, 129 insertions(+), 38 deletions(-) create mode 100644 api/logic/icons/IconUtils.cpp create mode 100644 api/logic/icons/IconUtils.h diff --git a/api/gui/icons/MMCIcon.cpp b/api/gui/icons/MMCIcon.cpp index 2a2d6e6f..5058717a 100644 --- a/api/gui/icons/MMCIcon.cpp +++ b/api/gui/icons/MMCIcon.cpp @@ -102,3 +102,17 @@ void MMCIcon::replace(IconType new_type, const QString& key) m_images[new_type].filename = QString(); m_images[new_type].key = key; } + +QString MMCIcon::getFilePath() const +{ + if(m_current_type == IconType::ToBeDeleted){ + return QString(); + } + return m_images[m_current_type].filename; +} + + +bool MMCIcon::isBuiltIn() const +{ + return m_current_type == IconType::Builtin; +} diff --git a/api/gui/icons/MMCIcon.h b/api/gui/icons/MMCIcon.h index c0eb5570..9fd1b9a2 100644 --- a/api/gui/icons/MMCIcon.h +++ b/api/gui/icons/MMCIcon.h @@ -46,4 +46,6 @@ struct MULTIMC_GUI_EXPORT MMCIcon void remove(IconType rm_type); void replace(IconType new_type, QIcon icon, QString path = QString()); void replace(IconType new_type, const QString &key); + bool isBuiltIn() const; + QString getFilePath() const; }; diff --git a/api/logic/CMakeLists.txt b/api/logic/CMakeLists.txt index 39850163..94da2682 100644 --- a/api/logic/CMakeLists.txt +++ b/api/logic/CMakeLists.txt @@ -182,9 +182,11 @@ set(NEWS_SOURCES # Icon interface set(ICONS_SOURCES - # News System + # Icons System and related code icons/IIconList.h icons/IIconList.cpp + icons/IconUtils.h + icons/IconUtils.cpp ) # Minecraft services status checker diff --git a/api/logic/InstanceImportTask.cpp b/api/logic/InstanceImportTask.cpp index bbab557a..1e93174c 100644 --- a/api/logic/InstanceImportTask.cpp +++ b/api/logic/InstanceImportTask.cpp @@ -6,6 +6,7 @@ #include "NullInstance.h" #include "settings/INISettingsObject.h" #include "icons/IIconList.h" +#include "icons/IconUtils.h" #include // FIXME: this does not belong here, it's Minecraft/Flame specific @@ -393,8 +394,9 @@ void InstanceImportTask::processMultiMC() else { m_instIcon = instance.iconKey(); - auto importIconPath = FS::PathCombine(instance.instanceRoot(), m_instIcon + ".png"); - if (QFile::exists(importIconPath)) + + auto importIconPath = IconUtils::findBestIconIn(instance.instanceRoot(), m_instIcon); + if (!importIconPath.isNull() && QFile::exists(importIconPath)) { // import icon auto iconList = ENV.icons(); diff --git a/api/logic/icons/IconUtils.cpp b/api/logic/icons/IconUtils.cpp new file mode 100644 index 00000000..1b6d7553 --- /dev/null +++ b/api/logic/icons/IconUtils.cpp @@ -0,0 +1,62 @@ +#include "IconUtils.h" + +#include "FileSystem.h" +#include + +#include + +namespace { +std::array validIconExtensions = { + "svg", + "png", + "ico", + "gif", + "jpg", + "jpeg" +}; +} + +namespace IconUtils{ + +QString findBestIconIn(const QString &folder, const QString & iconKey) { + int best_found = validIconExtensions.size(); + QString best_filename; + + QDirIterator it(folder, QDir::NoDotAndDotDot | QDir::Files, QDirIterator::NoIteratorFlags); + while (it.hasNext()) { + it.next(); + auto fileInfo = it.fileInfo(); + + if(fileInfo.completeBaseName() != iconKey) + continue; + + auto extension = fileInfo.suffix(); + + for(int i = 0; i < best_found; i++) { + if(extension == validIconExtensions[i]) { + best_found = i; + qDebug() << i << " : " << fileInfo.fileName(); + best_filename = fileInfo.fileName(); + } + } + } + return FS::PathCombine(folder, best_filename); +} + +QString getIconFilter() { + QString out; + QTextStream stream(&out); + stream << '('; + for(size_t i = 0; i < validIconExtensions.size() - 1; i++) { + if(i > 0) { + stream << " "; + } + stream << "*." << validIconExtensions[i]; + } + stream << " *." << validIconExtensions[validIconExtensions.size() - 1]; + stream << ')'; + return out; +} + +} + diff --git a/api/logic/icons/IconUtils.h b/api/logic/icons/IconUtils.h new file mode 100644 index 00000000..ce236946 --- /dev/null +++ b/api/logic/icons/IconUtils.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include "multimc_logic_export.h" + +namespace IconUtils { + +// Given a folder and an icon key, find 'best' of the icons with the given key in there and return its path +MULTIMC_LOGIC_EXPORT QString findBestIconIn(const QString &folder, const QString & iconKey); + +// Get icon file type filter for file browser dialogs +MULTIMC_LOGIC_EXPORT QString getIconFilter(); + +} diff --git a/application/dialogs/ExportInstanceDialog.cpp b/application/dialogs/ExportInstanceDialog.cpp index 5419b000..49c082e9 100644 --- a/application/dialogs/ExportInstanceDialog.cpp +++ b/application/dialogs/ExportInstanceDialog.cpp @@ -343,43 +343,37 @@ void SaveIcon(InstancePtr m_instance) auto iconKey = m_instance->iconKey(); auto iconList = MMC->icons(); auto mmcIcon = iconList->icon(iconKey); - if(mmcIcon) + if(!mmcIcon || mmcIcon->isBuiltIn()) { + return; + } + auto path = mmcIcon->getFilePath(); + if(!path.isNull()) { + QFileInfo inInfo (path); + FS::copy(path, FS::PathCombine(m_instance->instanceRoot(), inInfo.fileName())) (); + return; + } + auto & image = mmcIcon->m_images[mmcIcon->type()]; + auto & icon = image.icon; + auto sizes = icon.availableSizes(); + if(sizes.size() == 0) { - bool saveIcon = false; - switch(mmcIcon->type()) + return; + } + auto areaOf = [](QSize size) + { + return size.width() * size.height(); + }; + QSize largest = sizes[0]; + // find variant with largest area + for(auto size: sizes) + { + if(areaOf(largest) < areaOf(size)) { - case IconType::FileBased: - case IconType::Transient: - saveIcon = true; - default: - break; - } - if(saveIcon) - { - auto & image = mmcIcon->m_images[mmcIcon->type()]; - auto & icon = image.icon; - auto sizes = icon.availableSizes(); - if(sizes.size() == 0) - { - return; - } - auto areaOf = [](QSize size) - { - return size.width() * size.height(); - }; - QSize largest = sizes[0]; - // find variant with largest area - for(auto size: sizes) - { - if(areaOf(largest) < areaOf(size)) - { - largest = size; - } - } - auto pixmap = icon.pixmap(largest); - pixmap.save(FS::PathCombine(m_instance->instanceRoot(), iconKey + ".png")); + largest = size; } } + auto pixmap = icon.pixmap(largest); + pixmap.save(FS::PathCombine(m_instance->instanceRoot(), iconKey + ".png")); } bool ExportInstanceDialog::doExport() diff --git a/application/dialogs/IconPickerDialog.cpp b/application/dialogs/IconPickerDialog.cpp index 7727aa49..7f930717 100644 --- a/application/dialogs/IconPickerDialog.cpp +++ b/application/dialogs/IconPickerDialog.cpp @@ -25,6 +25,7 @@ #include "groupview/InstanceDelegate.h" #include "icons/IconList.h" +#include "icons/IconUtils.h" #include IconPickerDialog::IconPickerDialog(QWidget *parent) @@ -103,8 +104,8 @@ void IconPickerDialog::addNewIcon() //: The title of the select icons open file dialog QString selectIcons = tr("Select Icons"); //: The type of icon files - QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(), - tr("Icons") + "(*.png *.jpg *.jpeg *.ico *.svg *.gif)"); + auto filter = IconUtils::getIconFilter(); + QStringList fileNames = QFileDialog::getOpenFileNames(this, selectIcons, QString(), tr("Icons %1").arg(filter)); MMC->icons()->installIcons(fileNames); }