Merge pull request #1407 from TheKodeToad/icon-indexing
This commit is contained in:
53
launcher/ui/themes/IconTheme.cpp
Normal file
53
launcher/ui/themes/IconTheme.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "IconTheme.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QSettings>
|
||||
|
||||
IconTheme::IconTheme(const QString& id, const QString& path) : m_id(id), m_path(path) {}
|
||||
|
||||
bool IconTheme::load()
|
||||
{
|
||||
const QString path = m_path + "/index.theme";
|
||||
|
||||
if (!QFile::exists(path))
|
||||
return false;
|
||||
|
||||
QSettings settings(path, QSettings::IniFormat);
|
||||
settings.beginGroup("Icon Theme");
|
||||
m_name = settings.value("Name").toString();
|
||||
settings.endGroup();
|
||||
return !m_name.isNull();
|
||||
}
|
||||
|
||||
QString IconTheme::id()
|
||||
{
|
||||
return m_id;
|
||||
}
|
||||
|
||||
QString IconTheme::path()
|
||||
{
|
||||
return m_path;
|
||||
}
|
||||
|
||||
QString IconTheme::name()
|
||||
{
|
||||
return m_name;
|
||||
}
|
37
launcher/ui/themes/IconTheme.h
Normal file
37
launcher/ui/themes/IconTheme.h
Normal file
@ -0,0 +1,37 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-only
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
class IconTheme {
|
||||
public:
|
||||
IconTheme(const QString& id, const QString& path);
|
||||
IconTheme() = default;
|
||||
|
||||
bool load();
|
||||
QString id();
|
||||
QString path();
|
||||
QString name();
|
||||
|
||||
private:
|
||||
QString m_id;
|
||||
QString m_path;
|
||||
QString m_name;
|
||||
};
|
@ -2,6 +2,7 @@
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2022 Tayou <git@tayou.org>
|
||||
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* 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
|
||||
@ -31,9 +32,8 @@
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
ThemeManager::ThemeManager(MainWindow* mainWindow)
|
||||
ThemeManager::ThemeManager()
|
||||
{
|
||||
m_mainWindow = mainWindow;
|
||||
initializeThemes();
|
||||
initializeCatPacks();
|
||||
}
|
||||
@ -59,53 +59,110 @@ ITheme* ThemeManager::getTheme(QString themeId)
|
||||
return m_themes[themeId].get();
|
||||
}
|
||||
|
||||
QString ThemeManager::addIconTheme(IconTheme theme)
|
||||
{
|
||||
QString id = theme.id();
|
||||
if (m_icons.find(id) == m_icons.end())
|
||||
m_icons.emplace(id, std::move(theme));
|
||||
else
|
||||
themeWarningLog() << "IconTheme(" << id << ") not added to prevent id duplication";
|
||||
return id;
|
||||
}
|
||||
|
||||
void ThemeManager::initializeThemes()
|
||||
{
|
||||
// Icon themes
|
||||
{
|
||||
// TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies!
|
||||
// set icon theme search path!
|
||||
auto searchPaths = QIcon::themeSearchPaths();
|
||||
searchPaths.append("iconthemes");
|
||||
QIcon::setThemeSearchPaths(searchPaths);
|
||||
themeDebugLog() << "<> Icon themes initialized.";
|
||||
}
|
||||
initializeIcons();
|
||||
|
||||
// Initialize widget themes
|
||||
{
|
||||
themeDebugLog() << "<> Initializing Widget Themes";
|
||||
themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique<SystemTheme>());
|
||||
auto darkThemeId = addTheme(std::make_unique<DarkTheme>());
|
||||
themeDebugLog() << "Loading Built-in Theme:" << darkThemeId;
|
||||
themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique<BrightTheme>());
|
||||
initializeWidgets();
|
||||
}
|
||||
|
||||
// TODO: need some way to differentiate same name themes in different subdirectories (maybe smaller grey text next to theme name in
|
||||
// dropdown?)
|
||||
QString themeFolder = QDir("./themes/").absoluteFilePath("");
|
||||
themeDebugLog() << "Theme Folder Path: " << themeFolder;
|
||||
void ThemeManager::initializeIcons()
|
||||
{
|
||||
// TODO: icon themes and instance icons do not mesh well together. Rearrange and fix discrepancies!
|
||||
// set icon theme search path!
|
||||
themeDebugLog() << "<> Initializing Icon Themes";
|
||||
|
||||
QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
while (directoryIterator.hasNext()) {
|
||||
QDir dir(directoryIterator.next());
|
||||
QFileInfo themeJson(dir.absoluteFilePath("theme.json"));
|
||||
if (themeJson.exists()) {
|
||||
// Load "theme.json" based themes
|
||||
themeDebugLog() << "Loading JSON Theme from:" << themeJson.absoluteFilePath();
|
||||
addTheme(std::make_unique<CustomTheme>(getTheme(darkThemeId), themeJson, true));
|
||||
} else {
|
||||
// Load pure QSS Themes
|
||||
QDirIterator stylesheetFileIterator(dir.absoluteFilePath(""), { "*.qss", "*.css" }, QDir::Files);
|
||||
while (stylesheetFileIterator.hasNext()) {
|
||||
QFile customThemeFile(stylesheetFileIterator.next());
|
||||
QFileInfo customThemeFileInfo(customThemeFile);
|
||||
themeDebugLog() << "Loading QSS Theme from:" << customThemeFileInfo.absoluteFilePath();
|
||||
addTheme(std::make_unique<CustomTheme>(getTheme(darkThemeId), customThemeFileInfo, false));
|
||||
}
|
||||
}
|
||||
auto searchPaths = QIcon::themeSearchPaths();
|
||||
searchPaths.append(m_iconThemeFolder.path());
|
||||
QIcon::setThemeSearchPaths(searchPaths);
|
||||
|
||||
for (const QString& id : builtinIcons) {
|
||||
IconTheme theme(id, QString(":/icons/%1").arg(id));
|
||||
if (!theme.load()) {
|
||||
themeWarningLog() << "Couldn't load built-in icon theme" << id;
|
||||
continue;
|
||||
}
|
||||
|
||||
themeDebugLog() << "<> Widget themes initialized.";
|
||||
addIconTheme(std::move(theme));
|
||||
themeDebugLog() << "Loaded Built-In Icon Theme" << id;
|
||||
}
|
||||
|
||||
if (!m_iconThemeFolder.mkpath("."))
|
||||
themeWarningLog() << "Couldn't create icon theme folder";
|
||||
themeDebugLog() << "Icon Theme Folder Path: " << m_iconThemeFolder.absolutePath();
|
||||
|
||||
QDirIterator directoryIterator(m_iconThemeFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
while (directoryIterator.hasNext()) {
|
||||
QDir dir(directoryIterator.next());
|
||||
IconTheme theme(dir.dirName(), dir.path());
|
||||
if (!theme.load())
|
||||
continue;
|
||||
|
||||
addIconTheme(std::move(theme));
|
||||
themeDebugLog() << "Loaded Custom Icon Theme from" << dir.path();
|
||||
}
|
||||
|
||||
themeDebugLog() << "<> Icon themes initialized.";
|
||||
}
|
||||
|
||||
void ThemeManager::initializeWidgets()
|
||||
{
|
||||
themeDebugLog() << "<> Initializing Widget Themes";
|
||||
themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique<SystemTheme>());
|
||||
auto darkThemeId = addTheme(std::make_unique<DarkTheme>());
|
||||
themeDebugLog() << "Loading Built-in Theme:" << darkThemeId;
|
||||
themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique<BrightTheme>());
|
||||
|
||||
// TODO: need some way to differentiate same name themes in different subdirectories (maybe smaller grey text next to theme name in
|
||||
// dropdown?)
|
||||
|
||||
if (!m_applicationThemeFolder.mkpath("."))
|
||||
themeWarningLog() << "Couldn't create theme folder";
|
||||
themeDebugLog() << "Theme Folder Path: " << m_applicationThemeFolder.absolutePath();
|
||||
|
||||
QDirIterator directoryIterator(m_applicationThemeFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
while (directoryIterator.hasNext()) {
|
||||
QDir dir(directoryIterator.next());
|
||||
QFileInfo themeJson(dir.absoluteFilePath("theme.json"));
|
||||
if (themeJson.exists()) {
|
||||
// Load "theme.json" based themes
|
||||
themeDebugLog() << "Loading JSON Theme from:" << themeJson.absoluteFilePath();
|
||||
addTheme(std::make_unique<CustomTheme>(getTheme(darkThemeId), themeJson, true));
|
||||
} else {
|
||||
// Load pure QSS Themes
|
||||
QDirIterator stylesheetFileIterator(dir.absoluteFilePath(""), { "*.qss", "*.css" }, QDir::Files);
|
||||
while (stylesheetFileIterator.hasNext()) {
|
||||
QFile customThemeFile(stylesheetFileIterator.next());
|
||||
QFileInfo customThemeFileInfo(customThemeFile);
|
||||
themeDebugLog() << "Loading QSS Theme from:" << customThemeFileInfo.absoluteFilePath();
|
||||
addTheme(std::make_unique<CustomTheme>(getTheme(darkThemeId), customThemeFileInfo, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
themeDebugLog() << "<> Widget themes initialized.";
|
||||
}
|
||||
|
||||
QList<IconTheme*> ThemeManager::getValidIconThemes()
|
||||
{
|
||||
QList<IconTheme*> ret;
|
||||
ret.reserve(m_icons.size());
|
||||
for (auto&& [id, theme] : m_icons) {
|
||||
ret.append(&theme);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QList<ITheme*> ThemeManager::getValidApplicationThemes()
|
||||
@ -128,17 +185,39 @@ QList<CatPack*> ThemeManager::getValidCatPacks()
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ThemeManager::setIconTheme(const QString& name)
|
||||
bool ThemeManager::isValidIconTheme(const QString& id)
|
||||
{
|
||||
QIcon::setThemeName(name);
|
||||
return !id.isEmpty() && m_icons.find(id) != m_icons.end();
|
||||
}
|
||||
|
||||
void ThemeManager::applyCurrentlySelectedTheme(bool initial)
|
||||
bool ThemeManager::isValidApplicationTheme(const QString& id)
|
||||
{
|
||||
setIconTheme(APPLICATION->settings()->get("IconTheme").toString());
|
||||
themeDebugLog() << "<> Icon theme set.";
|
||||
setApplicationTheme(APPLICATION->settings()->get("ApplicationTheme").toString(), initial);
|
||||
themeDebugLog() << "<> Application theme set.";
|
||||
return !id.isEmpty() && m_themes.find(id) != m_themes.end();
|
||||
}
|
||||
|
||||
QDir ThemeManager::getIconThemesFolder()
|
||||
{
|
||||
return m_iconThemeFolder;
|
||||
}
|
||||
|
||||
QDir ThemeManager::getApplicationThemesFolder()
|
||||
{
|
||||
return m_applicationThemeFolder;
|
||||
}
|
||||
|
||||
QDir ThemeManager::getCatPacksFolder()
|
||||
{
|
||||
return m_catPacksFolder;
|
||||
}
|
||||
|
||||
void ThemeManager::setIconTheme(const QString& name)
|
||||
{
|
||||
if (m_icons.find(name) == m_icons.end()) {
|
||||
themeWarningLog() << "Tried to set invalid icon theme:" << name;
|
||||
return;
|
||||
}
|
||||
|
||||
QIcon::setThemeName(name);
|
||||
}
|
||||
|
||||
void ThemeManager::setApplicationTheme(const QString& name, bool initial)
|
||||
@ -154,6 +233,15 @@ void ThemeManager::setApplicationTheme(const QString& name, bool initial)
|
||||
}
|
||||
}
|
||||
|
||||
void ThemeManager::applyCurrentlySelectedTheme(bool initial)
|
||||
{
|
||||
auto settings = APPLICATION->settings();
|
||||
setIconTheme(settings->get("IconTheme").toString());
|
||||
themeDebugLog() << "<> Icon theme set.";
|
||||
setApplicationTheme(settings->get("ApplicationTheme").toString(), initial);
|
||||
themeDebugLog() << "<> Application theme set.";
|
||||
}
|
||||
|
||||
QString ThemeManager::getCatPack(QString catName)
|
||||
{
|
||||
auto catIter = m_catPacks.find(!catName.isEmpty() ? catName : APPLICATION->settings()->get("BackgroundCat").toString());
|
||||
@ -187,9 +275,9 @@ void ThemeManager::initializeCatPacks()
|
||||
for (auto [id, name] : defaultCats) {
|
||||
addCatPack(std::unique_ptr<CatPack>(new BasicCatPack(id, name)));
|
||||
}
|
||||
QDir catpacksDir("catpacks");
|
||||
QString catpacksFolder = catpacksDir.absoluteFilePath("");
|
||||
themeDebugLog() << "CatPacks Folder Path:" << catpacksFolder;
|
||||
if (!m_catPacksFolder.mkpath("."))
|
||||
themeWarningLog() << "Couldn't create catpacks folder";
|
||||
themeDebugLog() << "CatPacks Folder Path:" << m_catPacksFolder.absolutePath();
|
||||
|
||||
QStringList supportedImageFormats;
|
||||
for (auto format : QImageReader::supportedImageFormats()) {
|
||||
@ -206,9 +294,9 @@ void ThemeManager::initializeCatPacks()
|
||||
}
|
||||
};
|
||||
|
||||
loadFiles(catpacksDir);
|
||||
loadFiles(m_catPacksFolder);
|
||||
|
||||
QDirIterator directoryIterator(catpacksFolder, QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
QDirIterator directoryIterator(m_catPacksFolder.path(), QDir::Dirs | QDir::NoDotAndDotDot);
|
||||
while (directoryIterator.hasNext()) {
|
||||
QDir dir(directoryIterator.next());
|
||||
QFileInfo manifest(dir.absoluteFilePath("catpack.json"));
|
||||
|
@ -2,6 +2,7 @@
|
||||
/*
|
||||
* Prism Launcher - Minecraft Launcher
|
||||
* Copyright (C) 2022 Tayou <git@tayou.org>
|
||||
* Copyright (C) 2023 TheKodeToad <TheKodeToad@proton.me>
|
||||
*
|
||||
* 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
|
||||
@ -19,6 +20,7 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "IconTheme.h"
|
||||
#include "ui/MainWindow.h"
|
||||
#include "ui/themes/CatPack.h"
|
||||
#include "ui/themes/ITheme.h"
|
||||
@ -34,11 +36,17 @@ inline auto themeWarningLog()
|
||||
|
||||
class ThemeManager {
|
||||
public:
|
||||
ThemeManager(MainWindow* mainWindow);
|
||||
ThemeManager();
|
||||
|
||||
QList<IconTheme*> getValidIconThemes();
|
||||
QList<ITheme*> getValidApplicationThemes();
|
||||
void setIconTheme(const QString& name);
|
||||
bool isValidIconTheme(const QString& id);
|
||||
bool isValidApplicationTheme(const QString& id);
|
||||
QDir getIconThemesFolder();
|
||||
QDir getApplicationThemesFolder();
|
||||
QDir getCatPacksFolder();
|
||||
void applyCurrentlySelectedTheme(bool initial = false);
|
||||
void setIconTheme(const QString& name);
|
||||
void setApplicationTheme(const QString& name, bool initial = false);
|
||||
|
||||
/// @brief Returns the background based on selected and with events (Birthday, XMas, etc.)
|
||||
@ -49,12 +57,21 @@ class ThemeManager {
|
||||
|
||||
private:
|
||||
std::map<QString, std::unique_ptr<ITheme>> m_themes;
|
||||
std::map<QString, IconTheme> m_icons;
|
||||
QDir m_iconThemeFolder{ "iconthemes" };
|
||||
QDir m_applicationThemeFolder{ "themes" };
|
||||
QDir m_catPacksFolder{ "catpacks" };
|
||||
std::map<QString, std::unique_ptr<CatPack>> m_catPacks;
|
||||
MainWindow* m_mainWindow;
|
||||
|
||||
void initializeThemes();
|
||||
void initializeCatPacks();
|
||||
QString addTheme(std::unique_ptr<ITheme> theme);
|
||||
ITheme* getTheme(QString themeId);
|
||||
QString addIconTheme(IconTheme theme);
|
||||
QString addCatPack(std::unique_ptr<CatPack> catPack);
|
||||
void initializeIcons();
|
||||
void initializeWidgets();
|
||||
|
||||
const QStringList builtinIcons{ "pe_colored", "pe_light", "pe_dark", "pe_blue", "breeze_light", "breeze_dark",
|
||||
"OSX", "iOS", "flat", "flat_white", "multimc" };
|
||||
};
|
||||
|
Reference in New Issue
Block a user