Merge pull request #1407 from TheKodeToad/icon-indexing

This commit is contained in:
Sefa Eyeoglu 2023-08-15 10:43:29 +02:00 committed by GitHub
commit 7ba1e7d356
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 454 additions and 189 deletions

View File

@ -492,7 +492,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
m_settings.reset(new INISettingsObject({ BuildConfig.LAUNCHER_CONFIGFILE, "polymc.cfg", "multimc.cfg" }, this)); m_settings.reset(new INISettingsObject({ BuildConfig.LAUNCHER_CONFIGFILE, "polymc.cfg", "multimc.cfg" }, this));
// Theming // Theming
m_settings->registerSetting("IconTheme", QString("pe_colored")); m_settings->registerSetting("IconTheme", QString());
m_settings->registerSetting("ApplicationTheme", QString()); m_settings->registerSetting("ApplicationTheme", QString());
m_settings->registerSetting("BackgroundCat", QString("kitteh")); m_settings->registerSetting("BackgroundCat", QString("kitteh"));
@ -754,7 +754,7 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
} }
// Themes // Themes
m_themeManager = std::make_unique<ThemeManager>(m_mainWindow); m_themeManager = std::make_unique<ThemeManager>();
// initialize and load all instances // initialize and load all instances
{ {
@ -840,14 +840,13 @@ Application::Application(int& argc, char** argv) : QApplication(argc, argv)
} }
}); });
applyCurrentlySelectedTheme(true);
updateCapabilities(); updateCapabilities();
if (createSetupWizard()) { if (createSetupWizard()) {
return; return;
} }
m_themeManager->applyCurrentlySelectedTheme(true);
performMainStartupAction(); performMainStartupAction();
} }
@ -873,10 +872,20 @@ bool Application::createSetupWizard()
}(); }();
bool languageRequired = settings()->get("Language").toString().isEmpty(); bool languageRequired = settings()->get("Language").toString().isEmpty();
bool pasteInterventionRequired = settings()->get("PastebinURL") != ""; bool pasteInterventionRequired = settings()->get("PastebinURL") != "";
bool themeInterventionRequired = settings()->get("ApplicationTheme") == ""; bool validWidgets = m_themeManager->isValidApplicationTheme(settings()->get("ApplicationTheme").toString());
bool validIcons = m_themeManager->isValidIconTheme(settings()->get("IconTheme").toString());
bool themeInterventionRequired = !validWidgets || !validIcons;
bool wizardRequired = javaRequired || languageRequired || pasteInterventionRequired || themeInterventionRequired; bool wizardRequired = javaRequired || languageRequired || pasteInterventionRequired || themeInterventionRequired;
if (wizardRequired) { if (wizardRequired) {
// set default theme after going into theme wizard
if (!validIcons)
settings()->set("IconTheme", QString("pe_colored"));
if (!validWidgets)
settings()->set("ApplicationTheme", QString("system"));
m_themeManager->applyCurrentlySelectedTheme(true);
m_setupWizard = new SetupWizard(nullptr); m_setupWizard = new SetupWizard(nullptr);
if (languageRequired) { if (languageRequired) {
m_setupWizard->addPage(new LanguageWizardPage(m_setupWizard)); m_setupWizard->addPage(new LanguageWizardPage(m_setupWizard));
@ -891,9 +900,9 @@ bool Application::createSetupWizard()
} }
if (themeInterventionRequired) { if (themeInterventionRequired) {
settings()->set("ApplicationTheme", QString("system")); // set default theme after going into theme wizard
m_setupWizard->addPage(new ThemeWizardPage(m_setupWizard)); m_setupWizard->addPage(new ThemeWizardPage(m_setupWizard));
} }
connect(m_setupWizard, &QDialog::finished, this, &Application::setupWizardFinished); connect(m_setupWizard, &QDialog::finished, this, &Application::setupWizardFinished);
m_setupWizard->show(); m_setupWizard->show();
return true; return true;
@ -1070,26 +1079,6 @@ std::shared_ptr<JavaInstallList> Application::javalist()
return m_javalist; return m_javalist;
} }
QList<ITheme*> Application::getValidApplicationThemes()
{
return m_themeManager->getValidApplicationThemes();
}
void Application::applyCurrentlySelectedTheme(bool initial)
{
m_themeManager->applyCurrentlySelectedTheme(initial);
}
void Application::setApplicationTheme(const QString& name)
{
m_themeManager->setApplicationTheme(name);
}
void Application::setIconTheme(const QString& name)
{
m_themeManager->setIconTheme(name);
}
QIcon Application::getThemedIcon(const QString& name) QIcon Application::getThemedIcon(const QString& name)
{ {
if (name == "logo") { if (name == "logo") {
@ -1098,16 +1087,6 @@ QIcon Application::getThemedIcon(const QString& name)
return QIcon::fromTheme(name); return QIcon::fromTheme(name);
} }
QList<CatPack*> Application::getValidCatPacks()
{
return m_themeManager->getValidCatPacks();
}
QString Application::getCatPack(QString catName)
{
return m_themeManager->getCatPack(catName);
}
bool Application::openJsonEditor(const QString& filename) bool Application::openJsonEditor(const QString& filename)
{ {
const QString file = QDir::current().absoluteFilePath(filename); const QString file = QDir::current().absoluteFilePath(filename);

View File

@ -71,6 +71,7 @@ class TranslationsModel;
class ITheme; class ITheme;
class MCEditTool; class MCEditTool;
class ThemeManager; class ThemeManager;
class IconTheme;
namespace Meta { namespace Meta {
class Index; class Index;
@ -109,17 +110,7 @@ class Application : public QApplication {
QIcon getThemedIcon(const QString& name); QIcon getThemedIcon(const QString& name);
void setIconTheme(const QString& name); ThemeManager* themeManager() { return m_themeManager.get(); }
void applyCurrentlySelectedTheme(bool initial = false);
QList<ITheme*> getValidApplicationThemes();
void setApplicationTheme(const QString& name);
QList<CatPack*> getValidCatPacks();
QString getCatPack(QString catName = "");
shared_qobject_ptr<ExternalUpdater> updater() { return m_updater; } shared_qobject_ptr<ExternalUpdater> updater() { return m_updater; }

View File

@ -774,6 +774,8 @@ SET(LAUNCHER_SOURCES
ui/themes/ITheme.h ui/themes/ITheme.h
ui/themes/SystemTheme.cpp ui/themes/SystemTheme.cpp
ui/themes/SystemTheme.h ui/themes/SystemTheme.h
ui/themes/IconTheme.cpp
ui/themes/IconTheme.h
ui/themes/ThemeManager.cpp ui/themes/ThemeManager.cpp
ui/themes/ThemeManager.h ui/themes/ThemeManager.h
ui/themes/CatPack.cpp ui/themes/CatPack.cpp

View File

@ -101,7 +101,7 @@ bool openDirectory(const QString& path, [[maybe_unused]] bool ensureExists)
qDebug() << "Opening directory" << path; qDebug() << "Opening directory" << path;
QDir parentPath; QDir parentPath;
QDir dir(path); QDir dir(path);
if (!dir.exists()) { if (ensureExists && !dir.exists()) {
parentPath.mkpath(dir.absolutePath()); parentPath.mkpath(dir.absolutePath());
} }
auto f = [&]() { return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath())); }; auto f = [&]() { return QDesktopServices::openUrl(QUrl::fromLocalFile(dir.absolutePath())); };

View File

@ -1,5 +1,5 @@
[Icon Theme] [Icon Theme]
Name=multimc Name=Legacy
Comment=Default Icons Comment=Default Icons
Inherits=default Inherits=default
Directories=8x8,16x16,22x22,24x24,32x32,32x32/instances,48x48,50x50/instances,64x64,128x128/instances,256x256,scalable,scalable/instances Directories=8x8,16x16,22x22,24x24,32x32,32x32/instances,48x48,50x50/instances,64x64,128x128/instances,256x256,scalable,scalable/instances

View File

@ -1,5 +1,5 @@
[Icon Theme] [Icon Theme]
Name=pe_blue Name=Simple (Blue)
Comment=Icons by pexner (blue) Comment=Icons by pexner (blue)
Inherits=multimc Inherits=multimc
Directories=scalable Directories=scalable

View File

@ -1,5 +1,5 @@
[Icon Theme] [Icon Theme]
Name=pe_colored Name=Simple (Colored)
Comment=Icons by pexner (colored) Comment=Icons by pexner (colored)
Inherits=multimc Inherits=multimc
Directories=scalable Directories=scalable

View File

@ -1,5 +1,5 @@
[Icon Theme] [Icon Theme]
Name=pe_dark Name=Simple (Dark)
Comment=Icons by pexner (dark) Comment=Icons by pexner (dark)
Inherits=multimc Inherits=multimc
Directories=scalable Directories=scalable

View File

@ -1,5 +1,5 @@
[Icon Theme] [Icon Theme]
Name=pe_light Name=Simple (Light)
Comment=Icons by pexner (light) Comment=Icons by pexner (light)
Inherits=multimc Inherits=multimc
Directories=scalable Directories=scalable

View File

@ -627,7 +627,7 @@ void MainWindow::updateThemeMenu()
themeMenu = new QMenu(this); themeMenu = new QMenu(this);
} }
auto themes = APPLICATION->getValidApplicationThemes(); auto themes = APPLICATION->themeManager()->getValidApplicationThemes();
QActionGroup* themesGroup = new QActionGroup(this); QActionGroup* themesGroup = new QActionGroup(this);
@ -641,7 +641,7 @@ void MainWindow::updateThemeMenu()
themeAction->setActionGroup(themesGroup); themeAction->setActionGroup(themesGroup);
connect(themeAction, &QAction::triggered, [theme]() { connect(themeAction, &QAction::triggered, [theme]() {
APPLICATION->setApplicationTheme(theme->id()); APPLICATION->themeManager()->setApplicationTheme(theme->id());
APPLICATION->settings()->set("ApplicationTheme", theme->id()); APPLICATION->settings()->set("ApplicationTheme", theme->id());
}); });
} }
@ -1134,16 +1134,35 @@ void MainWindow::undoTrashInstance()
ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething()); ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething());
} }
void MainWindow::on_actionViewLauncherRootFolder_triggered()
{
DesktopServices::openDirectory(".");
}
void MainWindow::on_actionViewInstanceFolder_triggered() void MainWindow::on_actionViewInstanceFolder_triggered()
{ {
QString str = APPLICATION->settings()->get("InstanceDir").toString(); QString str = APPLICATION->settings()->get("InstanceDir").toString();
DesktopServices::openDirectory(str); DesktopServices::openDirectory(str);
} }
void MainWindow::on_actionViewLauncherRootFolder_triggered() void MainWindow::on_actionViewCentralModsFolder_triggered()
{ {
const QString dataPath = QDir::currentPath(); DesktopServices::openDirectory(APPLICATION->settings()->get("CentralModsDir").toString(), true);
DesktopServices::openDirectory(dataPath); }
void MainWindow::on_actionViewIconThemeFolder_triggered()
{
DesktopServices::openDirectory(APPLICATION->themeManager()->getIconThemesFolder().path());
}
void MainWindow::on_actionViewWidgetThemeFolder_triggered()
{
DesktopServices::openDirectory(APPLICATION->themeManager()->getApplicationThemesFolder().path());
}
void MainWindow::on_actionViewCatPackFolder_triggered()
{
DesktopServices::openDirectory(APPLICATION->themeManager()->getCatPacksFolder().path());
} }
void MainWindow::refreshInstances() void MainWindow::refreshInstances()
@ -1151,11 +1170,6 @@ void MainWindow::refreshInstances()
APPLICATION->instances()->loadList(); APPLICATION->instances()->loadList();
} }
void MainWindow::on_actionViewCentralModsFolder_triggered()
{
DesktopServices::openDirectory(APPLICATION->settings()->get("CentralModsDir").toString(), true);
}
void MainWindow::checkForUpdates() void MainWindow::checkForUpdates()
{ {
if (BuildConfig.UPDATER_ENABLED) { if (BuildConfig.UPDATER_ENABLED) {

View File

@ -109,16 +109,19 @@ class MainWindow : public QMainWindow {
void on_actionChangeInstIcon_triggered(); void on_actionChangeInstIcon_triggered();
void on_actionViewInstanceFolder_triggered();
void on_actionViewLauncherRootFolder_triggered(); void on_actionViewLauncherRootFolder_triggered();
void on_actionViewInstanceFolder_triggered();
void on_actionViewCentralModsFolder_triggered();
void on_actionViewIconThemeFolder_triggered();
void on_actionViewWidgetThemeFolder_triggered();
void on_actionViewCatPackFolder_triggered();
void on_actionViewSelectedInstFolder_triggered(); void on_actionViewSelectedInstFolder_triggered();
void refreshInstances(); void refreshInstances();
void on_actionViewCentralModsFolder_triggered();
void checkForUpdates(); void checkForUpdates();
void on_actionSettings_triggered(); void on_actionSettings_triggered();

View File

@ -186,9 +186,14 @@
<property name="toolTipsVisible"> <property name="toolTipsVisible">
<bool>true</bool> <bool>true</bool>
</property> </property>
<addaction name="actionViewInstanceFolder"/>
<addaction name="actionViewLauncherRootFolder"/> <addaction name="actionViewLauncherRootFolder"/>
<addaction name="separator"/>
<addaction name="actionViewInstanceFolder"/>
<addaction name="actionViewCentralModsFolder"/> <addaction name="actionViewCentralModsFolder"/>
<addaction name="separator"/>
<addaction name="actionViewIconThemeFolder"/>
<addaction name="actionViewWidgetThemeFolder"/>
<addaction name="actionViewCatPackFolder"/>
</widget> </widget>
<widget class="QMenu" name="accountsMenu"> <widget class="QMenu" name="accountsMenu">
<property name="title"> <property name="title">
@ -465,7 +470,8 @@
</action> </action>
<action name="actionExportInstanceZip"> <action name="actionExportInstanceZip">
<property name="icon"> <property name="icon">
<iconset theme="launcher"/> <iconset theme="launcher">
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Prism Launcher (zip)</string> <string>Prism Launcher (zip)</string>
@ -473,7 +479,8 @@
</action> </action>
<action name="actionExportInstanceMrPack"> <action name="actionExportInstanceMrPack">
<property name="icon"> <property name="icon">
<iconset theme="modrinth"/> <iconset theme="modrinth">
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Modrinth (mrpack)</string> <string>Modrinth (mrpack)</string>
@ -481,7 +488,8 @@
</action> </action>
<action name="actionExportInstanceFlamePack"> <action name="actionExportInstanceFlamePack">
<property name="icon"> <property name="icon">
<iconset theme="flame"/> <iconset theme="flame">
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>CurseForge (zip)</string> <string>CurseForge (zip)</string>
@ -489,7 +497,8 @@
</action> </action>
<action name="actionExportInstanceToModList"> <action name="actionExportInstanceToModList">
<property name="icon"> <property name="icon">
<iconset theme="new"/> <iconset theme="new">
<normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>Mod List</string> <string>Mod List</string>
@ -552,7 +561,7 @@
<normaloff>.</normaloff>.</iconset> <normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;View Instance Folder</string> <string>View &amp;Instance Folder</string>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Open the instance folder in a file browser.</string> <string>Open the instance folder in a file browser.</string>
@ -564,7 +573,7 @@
<normaloff>.</normaloff>.</iconset> <normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="text"> <property name="text">
<string>&amp;View Launcher Root Folder</string> <string>View Launcher &amp;Root Folder</string>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Open the launcher's root folder in a file browser.</string> <string>Open the launcher's root folder in a file browser.</string>
@ -719,6 +728,38 @@
<string>Open the %1 wiki</string> <string>Open the %1 wiki</string>
</property> </property>
</action> </action>
<action name="actionViewWidgetThemeFolder">
<property name="icon">
<iconset theme="viewfolder">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>View &amp;Widget Themes Folder</string>
</property>
<property name="toolTip">
<string>View Widget Theme Folder</string>
</property>
</action>
<action name="actionViewIconThemeFolder">
<property name="icon">
<iconset theme="viewfolder">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>View I&amp;con Theme Folder</string>
</property>
<property name="toolTip">
<string>View Icon Theme Folder</string>
</property>
</action>
<action name="actionViewCatPackFolder">
<property name="icon">
<iconset theme="viewfolder"/>
</property>
<property name="text">
<string>View Cat Packs Folder</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -47,8 +47,8 @@
#include <QScrollBar> #include <QScrollBar>
#include <QtMath> #include <QtMath>
#include <QDebug>
#include "VisualGroup.h" #include "VisualGroup.h"
#include "ui/themes/ThemeManager.h"
#include <Application.h> #include <Application.h>
#include <InstanceList.h> #include <InstanceList.h>
@ -446,7 +446,7 @@ void InstanceView::setPaintCat(bool visible)
{ {
m_catVisible = visible; m_catVisible = visible;
if (visible) if (visible)
m_catPixmap.load(APPLICATION->getCatPack()); m_catPixmap.load(APPLICATION->themeManager()->getCatPack());
else else
m_catPixmap = QPixmap(); m_catPixmap = QPixmap();
} }

View File

@ -61,7 +61,7 @@ void ThemeWizardPage::updateIcons()
void ThemeWizardPage::updateCat() void ThemeWizardPage::updateCat()
{ {
qDebug() << "Setting Cat"; qDebug() << "Setting Cat";
ui->catImagePreviewButton->setIcon(QIcon(QString(R"(%1)").arg(APPLICATION->getCatPack()))); ui->catImagePreviewButton->setIcon(QIcon(QString(R"(%1)").arg(APPLICATION->themeManager()->getCatPack())));
} }
void ThemeWizardPage::retranslate() void ThemeWizardPage::retranslate()

View 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;
}

View 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;
};

View File

@ -2,6 +2,7 @@
/* /*
* Prism Launcher - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Tayou <git@tayou.org> * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -31,9 +32,8 @@
#include "Application.h" #include "Application.h"
ThemeManager::ThemeManager(MainWindow* mainWindow) ThemeManager::ThemeManager()
{ {
m_mainWindow = mainWindow;
initializeThemes(); initializeThemes();
initializeCatPacks(); initializeCatPacks();
} }
@ -59,20 +59,66 @@ ITheme* ThemeManager::getTheme(QString themeId)
return m_themes[themeId].get(); 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() void ThemeManager::initializeThemes()
{ {
// Icon themes // Icon themes
{ initializeIcons();
// 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.";
}
// Initialize widget themes // Initialize widget themes
{ initializeWidgets();
}
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";
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;
}
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() << "<> Initializing Widget Themes";
themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique<SystemTheme>()); themeDebugLog() << "Loading Built-in Theme:" << addTheme(std::make_unique<SystemTheme>());
auto darkThemeId = addTheme(std::make_unique<DarkTheme>()); auto darkThemeId = addTheme(std::make_unique<DarkTheme>());
@ -81,10 +127,12 @@ void ThemeManager::initializeThemes()
// TODO: need some way to differentiate same name themes in different subdirectories (maybe smaller grey text next to theme name in // TODO: need some way to differentiate same name themes in different subdirectories (maybe smaller grey text next to theme name in
// dropdown?) // dropdown?)
QString themeFolder = QDir("./themes/").absoluteFilePath("");
themeDebugLog() << "Theme Folder Path: " << themeFolder;
QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot); 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()) { while (directoryIterator.hasNext()) {
QDir dir(directoryIterator.next()); QDir dir(directoryIterator.next());
QFileInfo themeJson(dir.absoluteFilePath("theme.json")); QFileInfo themeJson(dir.absoluteFilePath("theme.json"));
@ -105,7 +153,16 @@ void ThemeManager::initializeThemes()
} }
themeDebugLog() << "<> Widget themes initialized."; 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() QList<ITheme*> ThemeManager::getValidApplicationThemes()
@ -128,17 +185,39 @@ QList<CatPack*> ThemeManager::getValidCatPacks()
return ret; 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()); return !id.isEmpty() && m_themes.find(id) != m_themes.end();
themeDebugLog() << "<> Icon theme set."; }
setApplicationTheme(APPLICATION->settings()->get("ApplicationTheme").toString(), initial);
themeDebugLog() << "<> Application theme set."; 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) 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) QString ThemeManager::getCatPack(QString catName)
{ {
auto catIter = m_catPacks.find(!catName.isEmpty() ? catName : APPLICATION->settings()->get("BackgroundCat").toString()); 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) { for (auto [id, name] : defaultCats) {
addCatPack(std::unique_ptr<CatPack>(new BasicCatPack(id, name))); addCatPack(std::unique_ptr<CatPack>(new BasicCatPack(id, name)));
} }
QDir catpacksDir("catpacks"); if (!m_catPacksFolder.mkpath("."))
QString catpacksFolder = catpacksDir.absoluteFilePath(""); themeWarningLog() << "Couldn't create catpacks folder";
themeDebugLog() << "CatPacks Folder Path:" << catpacksFolder; themeDebugLog() << "CatPacks Folder Path:" << m_catPacksFolder.absolutePath();
QStringList supportedImageFormats; QStringList supportedImageFormats;
for (auto format : QImageReader::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()) { while (directoryIterator.hasNext()) {
QDir dir(directoryIterator.next()); QDir dir(directoryIterator.next());
QFileInfo manifest(dir.absoluteFilePath("catpack.json")); QFileInfo manifest(dir.absoluteFilePath("catpack.json"));

View File

@ -2,6 +2,7 @@
/* /*
* Prism Launcher - Minecraft Launcher * Prism Launcher - Minecraft Launcher
* Copyright (C) 2022 Tayou <git@tayou.org> * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -19,6 +20,7 @@
#include <QString> #include <QString>
#include "IconTheme.h"
#include "ui/MainWindow.h" #include "ui/MainWindow.h"
#include "ui/themes/CatPack.h" #include "ui/themes/CatPack.h"
#include "ui/themes/ITheme.h" #include "ui/themes/ITheme.h"
@ -34,11 +36,17 @@ inline auto themeWarningLog()
class ThemeManager { class ThemeManager {
public: public:
ThemeManager(MainWindow* mainWindow); ThemeManager();
QList<IconTheme*> getValidIconThemes();
QList<ITheme*> getValidApplicationThemes(); 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 applyCurrentlySelectedTheme(bool initial = false);
void setIconTheme(const QString& name);
void setApplicationTheme(const QString& name, bool initial = false); void setApplicationTheme(const QString& name, bool initial = false);
/// @brief Returns the background based on selected and with events (Birthday, XMas, etc.) /// @brief Returns the background based on selected and with events (Birthday, XMas, etc.)
@ -49,12 +57,21 @@ class ThemeManager {
private: private:
std::map<QString, std::unique_ptr<ITheme>> m_themes; 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; std::map<QString, std::unique_ptr<CatPack>> m_catPacks;
MainWindow* m_mainWindow;
void initializeThemes(); void initializeThemes();
void initializeCatPacks(); void initializeCatPacks();
QString addTheme(std::unique_ptr<ITheme> theme); QString addTheme(std::unique_ptr<ITheme> theme);
ITheme* getTheme(QString themeId); ITheme* getTheme(QString themeId);
QString addIconTheme(IconTheme theme);
QString addCatPack(std::unique_ptr<CatPack> catPack); 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" };
}; };

View File

@ -19,6 +19,7 @@
#include "ui_ThemeCustomizationWidget.h" #include "ui_ThemeCustomizationWidget.h"
#include "Application.h" #include "Application.h"
#include "DesktopServices.h"
#include "ui/themes/ITheme.h" #include "ui/themes/ITheme.h"
#include "ui/themes/ThemeManager.h" #include "ui/themes/ThemeManager.h"
@ -31,6 +32,13 @@ ThemeCustomizationWidget::ThemeCustomizationWidget(QWidget* parent) : QWidget(pa
connect(ui->widgetStyleComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, connect(ui->widgetStyleComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&ThemeCustomizationWidget::applyWidgetTheme); &ThemeCustomizationWidget::applyWidgetTheme);
connect(ui->backgroundCatComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ThemeCustomizationWidget::applyCatTheme); connect(ui->backgroundCatComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ThemeCustomizationWidget::applyCatTheme);
connect(ui->iconsFolder, &QPushButton::clicked, this,
[] { DesktopServices::openDirectory(APPLICATION->themeManager()->getIconThemesFolder().path()); });
connect(ui->widgetStyleFolder, &QPushButton::clicked, this,
[] { DesktopServices::openDirectory(APPLICATION->themeManager()->getApplicationThemesFolder().path()); });
connect(ui->catPackFolder, &QPushButton::clicked, this,
[] { DesktopServices::openDirectory(APPLICATION->themeManager()->getCatPacksFolder().path()); });
} }
ThemeCustomizationWidget::~ThemeCustomizationWidget() ThemeCustomizationWidget::~ThemeCustomizationWidget()
@ -67,7 +75,7 @@ void ThemeCustomizationWidget::showFeatures(ThemeFields features)
ui->iconsComboBox->setEnabled(features & ThemeFields::ICONS); ui->iconsComboBox->setEnabled(features & ThemeFields::ICONS);
ui->iconsLabel->setEnabled(features & ThemeFields::ICONS); ui->iconsLabel->setEnabled(features & ThemeFields::ICONS);
ui->widgetStyleComboBox->setEnabled(features & ThemeFields::WIDGETS); ui->widgetStyleComboBox->setEnabled(features & ThemeFields::WIDGETS);
ui->widgetThemeLabel->setEnabled(features & ThemeFields::WIDGETS); ui->widgetStyleLabel->setEnabled(features & ThemeFields::WIDGETS);
ui->backgroundCatComboBox->setEnabled(features & ThemeFields::CAT); ui->backgroundCatComboBox->setEnabled(features & ThemeFields::CAT);
ui->backgroundCatLabel->setEnabled(features & ThemeFields::CAT); ui->backgroundCatLabel->setEnabled(features & ThemeFields::CAT);
} }
@ -76,11 +84,10 @@ void ThemeCustomizationWidget::applyIconTheme(int index)
{ {
auto settings = APPLICATION->settings(); auto settings = APPLICATION->settings();
auto originalIconTheme = settings->get("IconTheme").toString(); auto originalIconTheme = settings->get("IconTheme").toString();
auto& newIconTheme = m_iconThemeOptions[index].first; auto newIconTheme = ui->iconsComboBox->currentData().toString();
settings->set("IconTheme", newIconTheme);
if (originalIconTheme != newIconTheme) { if (originalIconTheme != newIconTheme) {
APPLICATION->applyCurrentlySelectedTheme(); settings->set("IconTheme", newIconTheme);
APPLICATION->themeManager()->applyCurrentlySelectedTheme();
} }
emit currentIconThemeChanged(index); emit currentIconThemeChanged(index);
@ -93,7 +100,7 @@ void ThemeCustomizationWidget::applyWidgetTheme(int index)
auto newAppTheme = ui->widgetStyleComboBox->currentData().toString(); auto newAppTheme = ui->widgetStyleComboBox->currentData().toString();
if (originalAppTheme != newAppTheme) { if (originalAppTheme != newAppTheme) {
settings->set("ApplicationTheme", newAppTheme); settings->set("ApplicationTheme", newAppTheme);
APPLICATION->applyCurrentlySelectedTheme(); APPLICATION->themeManager()->applyCurrentlySelectedTheme();
} }
emit currentWidgetThemeChanged(index); emit currentWidgetThemeChanged(index);
@ -121,18 +128,23 @@ void ThemeCustomizationWidget::loadSettings()
{ {
auto settings = APPLICATION->settings(); auto settings = APPLICATION->settings();
auto iconTheme = settings->get("IconTheme").toString(); {
for (auto& iconThemeFromList : m_iconThemeOptions) { auto currentIconTheme = settings->get("IconTheme").toString();
QIcon iconForComboBox = QIcon(QString(":/icons/%1/scalable/settings").arg(iconThemeFromList.first)); auto iconThemes = APPLICATION->themeManager()->getValidIconThemes();
ui->iconsComboBox->addItem(iconForComboBox, iconThemeFromList.second); int idx = 0;
if (iconTheme == iconThemeFromList.first) { for (auto iconTheme : iconThemes) {
ui->iconsComboBox->setCurrentIndex(ui->iconsComboBox->count() - 1); QIcon iconForComboBox = QIcon(iconTheme->path() + "/scalable/settings");
ui->iconsComboBox->addItem(iconForComboBox, iconTheme->name(), iconTheme->id());
if (currentIconTheme == iconTheme->id()) {
ui->iconsComboBox->setCurrentIndex(idx);
}
idx++;
} }
} }
{ {
auto currentTheme = settings->get("ApplicationTheme").toString(); auto currentTheme = settings->get("ApplicationTheme").toString();
auto themes = APPLICATION->getValidApplicationThemes(); auto themes = APPLICATION->themeManager()->getValidApplicationThemes();
int idx = 0; int idx = 0;
for (auto& theme : themes) { for (auto& theme : themes) {
ui->widgetStyleComboBox->addItem(theme->name(), theme->id()); ui->widgetStyleComboBox->addItem(theme->name(), theme->id());
@ -144,7 +156,7 @@ void ThemeCustomizationWidget::loadSettings()
} }
auto cat = settings->get("BackgroundCat").toString(); auto cat = settings->get("BackgroundCat").toString();
for (auto& catFromList : APPLICATION->getValidCatPacks()) { for (auto& catFromList : APPLICATION->themeManager()->getValidCatPacks()) {
QIcon catIcon = QIcon(QString("%1").arg(catFromList->path())); QIcon catIcon = QIcon(QString("%1").arg(catFromList->path()));
ui->backgroundCatComboBox->addItem(catIcon, catFromList->name(), catFromList->id()); ui->backgroundCatComboBox->addItem(catIcon, catFromList->name(), catFromList->id());
if (cat == catFromList->id()) { if (cat == catFromList->id()) {

View File

@ -31,7 +31,7 @@ class ThemeCustomizationWidget : public QWidget {
public: public:
explicit ThemeCustomizationWidget(QWidget* parent = nullptr); explicit ThemeCustomizationWidget(QWidget* parent = nullptr);
~ThemeCustomizationWidget(); ~ThemeCustomizationWidget() override;
void showFeatures(ThemeFields features); void showFeatures(ThemeFields features);
@ -52,18 +52,4 @@ class ThemeCustomizationWidget : public QWidget {
private: private:
Ui::ThemeCustomizationWidget* ui; Ui::ThemeCustomizationWidget* ui;
// TODO finish implementing
QList<std::pair<QString, QString>> m_iconThemeOptions{ { "pe_colored", QObject::tr("Simple (Colored Icons)") },
{ "pe_light", QObject::tr("Simple (Light Icons)") },
{ "pe_dark", QObject::tr("Simple (Dark Icons)") },
{ "pe_blue", QObject::tr("Simple (Blue Icons)") },
{ "breeze_light", QObject::tr("Breeze Light") },
{ "breeze_dark", QObject::tr("Breeze Dark") },
{ "OSX", QObject::tr("OSX") },
{ "iOS", QObject::tr("iOS") },
{ "flat", QObject::tr("Flat") },
{ "flat_white", QObject::tr("Flat (White)") },
{ "multimc", QObject::tr("Legacy") },
{ "custom", QObject::tr("Custom") } };
}; };

View File

@ -40,6 +40,8 @@
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<layout class="QHBoxLayout" name="iconsLayout">
<item>
<widget class="QComboBox" name="iconsComboBox"> <widget class="QComboBox" name="iconsComboBox">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -52,10 +54,29 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0"> <item>
<widget class="QLabel" name="widgetThemeLabel"> <widget class="QPushButton" name="iconsFolder">
<property name="toolTip">
<string>View icon themes folder.</string>
</property>
<property name="text"> <property name="text">
<string>&amp;Colors</string> <string/>
</property>
<property name="icon">
<iconset theme="viewfolder">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="widgetStyleLabel">
<property name="text">
<string>&amp;Widgets</string>
</property> </property>
<property name="buddy"> <property name="buddy">
<cstring>widgetStyleComboBox</cstring> <cstring>widgetStyleComboBox</cstring>
@ -63,6 +84,8 @@
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<layout class="QHBoxLayout" name="widgetStyleLayout">
<item>
<widget class="QComboBox" name="widgetStyleComboBox"> <widget class="QComboBox" name="widgetStyleComboBox">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -75,6 +98,25 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="widgetStyleFolder">
<property name="toolTip">
<string>View widget themes folder.</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset theme="viewfolder">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="backgroundCatLabel"> <widget class="QLabel" name="backgroundCatLabel">
<property name="toolTip"> <property name="toolTip">
@ -89,7 +131,7 @@
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="catLayout">
<item> <item>
<widget class="QComboBox" name="backgroundCatComboBox"> <widget class="QComboBox" name="backgroundCatComboBox">
<property name="sizePolicy"> <property name="sizePolicy">
@ -107,15 +149,15 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="catInfoLabel"> <widget class="QPushButton" name="catPackFolder">
<property name="toolTip"> <property name="toolTip">
<string>The cat appears in the background and is not shown by default. It is only made visible when pressing the Cat button in the Toolbar.</string> <string>View cat packs folder.</string>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="about"> <iconset theme="viewfolder">
<normaloff>.</normaloff>.</iconset> <normaloff>.</normaloff>.</iconset>
</property> </property>
<property name="flat"> <property name="flat">