diff options
-rw-r--r-- | launcher/Application.cpp | 70 | ||||
-rw-r--r-- | launcher/Application.h | 9 | ||||
-rw-r--r-- | launcher/CMakeLists.txt | 2 | ||||
-rw-r--r-- | launcher/ui/themes/CustomTheme.cpp | 184 | ||||
-rw-r--r-- | launcher/ui/themes/CustomTheme.h | 43 | ||||
-rw-r--r-- | launcher/ui/themes/SystemTheme.cpp | 49 | ||||
-rw-r--r-- | launcher/ui/themes/ThemeManager.cpp | 152 | ||||
-rw-r--r-- | launcher/ui/themes/ThemeManager.h | 44 |
8 files changed, 436 insertions, 117 deletions
diff --git a/launcher/Application.cpp b/launcher/Application.cpp index 2da8ac56..7b33361c 100644 --- a/launcher/Application.cpp +++ b/launcher/Application.cpp @@ -1,7 +1,10 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> + * Copyright (C) 2022 Tayou <tayou@gmx.net> + * + * PolyMC - Minecraft Launcher * Copyright (C) 2022 Lenny McLennington <lenny@sneed.church> * * This program is free software: you can redistribute it and/or modify @@ -54,12 +57,6 @@ #include "ui/pages/global/APIPage.h" #include "ui/pages/global/CustomCommandsPage.h" -#include "ui/themes/ITheme.h" -#include "ui/themes/SystemTheme.h" -#include "ui/themes/DarkTheme.h" -#include "ui/themes/BrightTheme.h" -#include "ui/themes/CustomTheme.h" - #ifdef Q_OS_WIN #include "ui/WinDarkmode.h" #include <versionhelpers.h> @@ -749,28 +746,11 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) qDebug() << "<> Instance icons intialized."; } - // Icon themes + // 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); - qDebug() << "<> Icon themes initialized."; - } + m_themeManager = new ThemeManager(m_mainWindow); - // Initialize widget themes - { - auto insertTheme = [this](ITheme * theme) - { - m_themes.insert(std::make_pair(theme->id(), std::unique_ptr<ITheme>(theme))); - }; - auto darkTheme = new DarkTheme(); - insertTheme(new SystemTheme()); - insertTheme(darkTheme); - insertTheme(new BrightTheme()); - insertTheme(new CustomTheme(darkTheme, "custom")); - qDebug() << "<> Widget themes initialized."; + m_themeManager->InitializeThemes(); } // initialize and load all instances @@ -880,6 +860,10 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv) performMainStartupAction(); } +ThemeManager* Application::getThemeManager() { + return Application::m_themeManager; +} + bool Application::createSetupWizard() { bool javaRequired = [&]() @@ -1127,43 +1111,17 @@ std::shared_ptr<JavaInstallList> Application::javalist() std::vector<ITheme *> Application::getValidApplicationThemes() { - std::vector<ITheme *> ret; - auto iter = m_themes.cbegin(); - while (iter != m_themes.cend()) - { - ret.push_back((*iter).second.get()); - iter++; - } - return ret; + return m_themeManager->getValidApplicationThemes(); } void Application::setApplicationTheme(const QString& name, bool initial) { - auto systemPalette = qApp->palette(); - auto themeIter = m_themes.find(name); - if(themeIter != m_themes.end()) - { - auto & theme = (*themeIter).second; - theme->apply(initial); -#ifdef Q_OS_WIN - if (m_mainWindow && IsWindows10OrGreater()) { - if (QString::compare(theme->id(), "dark") == 0) { - WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), true); - } else { - WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), false); - } - } -#endif - } - else - { - qWarning() << "Tried to set invalid theme:" << name; - } + m_themeManager->setApplicationTheme(name, initial); } void Application::setIconTheme(const QString& name) { - QIcon::setThemeName(name); + m_themeManager->setIconTheme(name); } QIcon Application::getThemedIcon(const QString& name) diff --git a/launcher/Application.h b/launcher/Application.h index 8fa0ab10..33d8db29 100644 --- a/launcher/Application.h +++ b/launcher/Application.h @@ -1,7 +1,8 @@ // SPDX-License-Identifier: GPL-3.0-only /* - * PolyMC - Minecraft Launcher + * Prism Launcher * Copyright (C) 2022 Sefa Eyeoglu <contact@scrumplex.net> + * Copyright (C) 2022 Tayou <tayou@gmx.net> * * 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 @@ -44,6 +45,8 @@ #include <QUrl> #include <updater/GoUpdate.h> +#include "ui/themes/ThemeManager.h" + #include <BaseInstance.h> #include "minecraft/launch/MinecraftServerTarget.h" @@ -198,6 +201,8 @@ public: void ShowGlobalSettings(class QWidget * parent, QString open_page = QString()); + ThemeManager* getThemeManager(); + signals: void updateAllowedChanged(bool status); void globalSettingsAboutToOpen(); @@ -255,9 +260,9 @@ private: std::shared_ptr<JavaInstallList> m_javalist; std::shared_ptr<TranslationsModel> m_translations; std::shared_ptr<GenericPageProvider> m_globalSettingsProvider; - std::map<QString, std::unique_ptr<ITheme>> m_themes; std::unique_ptr<MCEditTool> m_mcedit; QSet<QString> m_features; + ThemeManager* m_themeManager; QMap<QString, std::shared_ptr<BaseProfilerFactory>> m_profilers; diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt index 0dae47df..5b0d9282 100644 --- a/launcher/CMakeLists.txt +++ b/launcher/CMakeLists.txt @@ -650,6 +650,8 @@ SET(LAUNCHER_SOURCES ui/themes/ITheme.h ui/themes/SystemTheme.cpp ui/themes/SystemTheme.h + ui/themes/ThemeManager.cpp + ui/themes/ThemeManager.h # Processes LaunchController.h diff --git a/launcher/ui/themes/CustomTheme.cpp b/launcher/ui/themes/CustomTheme.cpp index 3e3e27de..3c35bf37 100644 --- a/launcher/ui/themes/CustomTheme.cpp +++ b/launcher/ui/themes/CustomTheme.cpp @@ -1,12 +1,49 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher + * Copyright (C) 2022 Tayou <tayou@gmx.net> + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Authors: Andrew Okin + * Peterix + * Orochimarufan <orochimarufan.x3@gmail.com> + * + * 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 "CustomTheme.h" -#include <QDir> #include <Json.h> #include <FileSystem.h> +#include "ThemeManager.h" const char * themeFile = "theme.json"; -const char * styleFile = "themeStyle.css"; -static bool readThemeJson(const QString &path, QPalette &palette, double &fadeAmount, QColor &fadeColor, QString &name, QString &widgets) +static bool readThemeJson(const QString &path, QPalette &palette, double &fadeAmount, QColor &fadeColor, QString &name, QString &widgets, QString &qssFilePath, bool &dataIncomplete) { QFileInfo pathInfo(path); if(pathInfo.exists() && pathInfo.isFile()) @@ -15,8 +52,11 @@ static bool readThemeJson(const QString &path, QPalette &palette, double &fadeAm { auto doc = Json::requireDocument(path, "Theme JSON file"); const QJsonObject root = doc.object(); + dataIncomplete = !root.contains("qssFilePath"); name = Json::requireString(root, "name", "Theme name"); widgets = Json::requireString(root, "widgets", "Qt widget theme"); + qssFilePath = Json::ensureString(root, "qssFilePath", "themeStyle.css"); + //auto colorFileList = Json::ensureArray(root, "colorFiles"); auto colorsRoot = Json::requireObject(root, "colors", "colors object"); auto readColor = [&](QString colorName) -> QColor { @@ -26,7 +66,7 @@ static bool readThemeJson(const QString &path, QPalette &palette, double &fadeAm QColor color(colorValue); if(!color.isValid()) { - qWarning() << "Color value" << colorValue << "for" << colorName << "was not recognized."; + themeWarningLog << "Color value" << colorValue << "for" << colorName << "was not recognized."; return QColor(); } return color; @@ -42,7 +82,7 @@ static bool readThemeJson(const QString &path, QPalette &palette, double &fadeAm } else { - qDebug() << "Color value for" << colorName << "was not present."; + themeDebugLog << "Color value for" << colorName << "was not present."; } }; @@ -68,23 +108,24 @@ static bool readThemeJson(const QString &path, QPalette &palette, double &fadeAm } catch (const Exception &e) { - qWarning() << "Couldn't load theme json: " << e.cause(); + themeWarningLog << "Couldn't load theme json: " << e.cause(); return false; } } else { - qDebug() << "No theme json present."; + themeDebugLog << "No theme json present."; return false; } return true; } -static bool writeThemeJson(const QString &path, const QPalette &palette, double fadeAmount, QColor fadeColor, QString name, QString widgets) +static bool writeThemeJson(const QString &path, const QPalette &palette, double fadeAmount, QColor fadeColor, QString name, QString widgets, QString qssFilePath) { QJsonObject rootObj; rootObj.insert("name", name); rootObj.insert("widgets", widgets); + rootObj.insert("qssFilePath", qssFilePath); QJsonObject colorsObj; auto insertColor = [&](QPalette::ColorRole role, QString colorName) @@ -119,75 +160,112 @@ static bool writeThemeJson(const QString &path, const QPalette &palette, double } catch (const Exception &e) { - qWarning() << "Failed to write theme json to" << path; + themeWarningLog << "Failed to write theme json to" << path; return false; } } -CustomTheme::CustomTheme(ITheme* baseTheme, QString folder) +/// @brief +/// @param baseTheme Base Theme +/// @param fileInfo FileInfo object for file to load +/// @param isManifest whether to load a theme manifest or a qss file +CustomTheme::CustomTheme(ITheme* baseTheme, QFileInfo& fileInfo, bool isManifest) { - m_id = folder; - QString path = FS::PathCombine("themes", m_id); - QString pathResources = FS::PathCombine("themes", m_id, "resources"); + if (isManifest) { + m_id = fileInfo.dir().dirName(); - qDebug() << "Loading theme" << m_id; + QString path = FS::PathCombine("themes", m_id); + QString pathResources = FS::PathCombine("themes", m_id, "resources"); - if(!FS::ensureFolderPathExists(path) || !FS::ensureFolderPathExists(pathResources)) - { - qWarning() << "couldn't create folder for theme!"; - m_palette = baseTheme->colorScheme(); - m_styleSheet = baseTheme->appStyleSheet(); - return; - } + if(!FS::ensureFolderPathExists(path) || !FS::ensureFolderPathExists(pathResources)) + { + themeWarningLog << "X couldn't create folder for theme!"; + m_palette = baseTheme->colorScheme(); + m_styleSheet = baseTheme->appStyleSheet(); + return; + } - auto themeFilePath = FS::PathCombine(path, themeFile); + auto themeFilePath = FS::PathCombine(path, themeFile); + + bool jsonDataIncomplete = false; - m_palette = baseTheme->colorScheme(); - if (!readThemeJson(themeFilePath, m_palette, m_fadeAmount, m_fadeColor, m_name, m_widgets)) - { - m_name = "Custom"; m_palette = baseTheme->colorScheme(); - m_fadeColor = baseTheme->fadeColor(); - m_fadeAmount = baseTheme->fadeAmount(); - m_widgets = baseTheme->qtTheme(); + if (!readThemeJson(themeFilePath, m_palette, m_fadeAmount, m_fadeColor, m_name, m_widgets, m_qssFilePath, jsonDataIncomplete)) + { + themeDebugLog << "Did not read theme json file correctly, writing new one to: " << themeFilePath; + m_name = "Custom"; + m_palette = baseTheme->colorScheme(); + m_fadeColor = baseTheme->fadeColor(); + m_fadeAmount = baseTheme->fadeAmount(); + m_widgets = baseTheme->qtTheme(); + m_qssFilePath = "themeStyle.css"; - QFileInfo info(themeFilePath); - if(!info.exists()) + QFileInfo info(themeFilePath); + } + else { - writeThemeJson(themeFilePath, m_palette, m_fadeAmount, m_fadeColor, "Custom", m_widgets); + m_palette = fadeInactive(m_palette, m_fadeAmount, m_fadeColor); } - } - else - { - m_palette = fadeInactive(m_palette, m_fadeAmount, m_fadeColor); - } - auto cssFilePath = FS::PathCombine(path, styleFile); - QFileInfo info (cssFilePath); - if(info.isFile()) - { - try + if(jsonDataIncomplete) { - // TODO: validate css? - m_styleSheet = QString::fromUtf8(FS::read(cssFilePath)); + writeThemeJson(fileInfo.absoluteFilePath(), m_palette, m_fadeAmount, m_fadeColor, m_name, m_widgets, m_qssFilePath); } - catch (const Exception &e) + + auto cssFilePath = FS::PathCombine(path, m_qssFilePath); + QFileInfo info (cssFilePath); + if(info.isFile()) + { + try + { + // TODO: validate css? + m_styleSheet = QString::fromUtf8(FS::read(cssFilePath)); + } + catch (const Exception &e) + { + themeWarningLog << "X Couldn't load css:" << e.cause() << "from" << cssFilePath; + m_styleSheet = baseTheme->appStyleSheet(); + } + } + else { - qWarning() << "Couldn't load css:" << e.cause() << "from" << cssFilePath; + themeDebugLog << "X No theme css present."; m_styleSheet = baseTheme->appStyleSheet(); + try + { + FS::write(cssFilePath, m_styleSheet.toUtf8()); + } + catch (const Exception &e) + { + themeWarningLog << "X Couldn't write css:" << e.cause() << "to" << cssFilePath; + } } - } - else - { - qDebug() << "No theme css present."; - m_styleSheet = baseTheme->appStyleSheet(); + } else { + m_id = fileInfo.fileName(); + m_name = fileInfo.baseName(); + QString path = fileInfo.filePath(); + //themeDebugLog << "Theme ID: " << m_id; + //themeDebugLog << "Theme Name: " << m_name; + //themeDebugLog << "Theme Path: " << path; + + if(!FS::ensureFilePathExists(path)) + { + themeWarningLog << m_name << " Theme file path doesn't exist!"; + m_palette = baseTheme->colorScheme(); + m_styleSheet = baseTheme->appStyleSheet(); + return; + } + + m_palette = baseTheme->colorScheme(); try { - FS::write(cssFilePath, m_styleSheet.toUtf8()); + // TODO: validate qss? + m_styleSheet = QString::fromUtf8(FS::read(path)); } catch (const Exception &e) { - qWarning() << "Couldn't write css:" << e.cause() << "to" << cssFilePath; + themeWarningLog << "Couldn't load qss:" << e.cause() << "from" << path; + m_styleSheet = baseTheme->appStyleSheet(); } } } diff --git a/launcher/ui/themes/CustomTheme.h b/launcher/ui/themes/CustomTheme.h index d216895d..f4a7b737 100644 --- a/launcher/ui/themes/CustomTheme.h +++ b/launcher/ui/themes/CustomTheme.h @@ -1,11 +1,51 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher + * Copyright (C) 2022 Tayou <tayou@gmx.net> + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Authors: Andrew Okin + * Peterix + * Orochimarufan <orochimarufan.x3@gmail.com> + * + * 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. + */ #pragma once #include "ITheme.h" +#include <QFile> +#include <QDir> class CustomTheme: public ITheme { public: - CustomTheme(ITheme * baseTheme, QString folder); + CustomTheme(ITheme * baseTheme, QFileInfo& file, bool isManifest); virtual ~CustomTheme() {} QString id() override; @@ -27,5 +67,6 @@ private: /* data */ QString m_name; QString m_id; QString m_widgets; + QString m_qssFilePath; }; diff --git a/launcher/ui/themes/SystemTheme.cpp b/launcher/ui/themes/SystemTheme.cpp index 49b1afaa..b8eb2a3c 100644 --- a/launcher/ui/themes/SystemTheme.cpp +++ b/launcher/ui/themes/SystemTheme.cpp @@ -1,30 +1,69 @@ +// SPDX-License-Identifier: GPL-3.0-only +/* + * Prism Launcher + * Copyright (C) 2022 Tayou <tayou@gmx.net> + * + * 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/>. + * + * This file incorporates work covered by the following copyright and + * permission notice: + * + * Copyright 2013-2021 MultiMC Contributors + * + * Authors: Andrew Okin + * Peterix + * Orochimarufan <orochimarufan.x3@gmail.com> + * + * 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 "SystemTheme.h" #include <QApplication> #include <QStyle> #include <QStyleFactory> #include <QDebug> +#include "ThemeManager.h" SystemTheme::SystemTheme() { - qDebug() << "Determining System Theme..."; + themeDebugLog << "Determining System Theme..."; const auto & style = QApplication::style(); systemPalette = style->standardPalette(); QString lowerThemeName = style->objectName(); - qDebug() << "System theme seems to be:" << lowerThemeName; + themeDebugLog << "System theme seems to be:" << lowerThemeName; QStringList styles = QStyleFactory::keys(); for(auto &st: styles) { - qDebug() << "Considering theme from theme factory:" << st.toLower(); + themeDebugLog << "Considering theme from theme factory:" << st.toLower(); if(st.toLower() == lowerThemeName) { systemTheme = st; - qDebug() << "System theme has been determined to be:" << systemTheme; + themeDebugLog << "System theme has been determined to be:" << systemTheme; return; } } // fall back to fusion if we can't find the current theme. systemTheme = "Fusion"; - qDebug() << "System theme not found, defaulted to Fusion"; + themeDebugLog << "System theme not found, defaulted to Fusion"; } void SystemTheme::apply(bool initial) diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp new file mode 100644 index 00000000..6e1566d2 --- /dev/null +++ b/launcher/ui/themes/ThemeManager.cpp @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher
+ * Copyright (C) 2022 Tayou <tayou@gmx.net>
+ *
+ * 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 "ThemeManager.h"
+
+#include "ui/themes/SystemTheme.h"
+#include "ui/themes/DarkTheme.h"
+#include "ui/themes/BrightTheme.h"
+#include "ui/themes/CustomTheme.h"
+#include <QDir>
+#include <QDirIterator>
+#include <QIcon>
+#include <QApplication>
+
+#include "Application.h"
+
+#ifdef Q_OS_WIN
+#include <versionhelpers.h>
+#include "ui/WinDarkmode.h"
+#endif
+
+ThemeManager::ThemeManager(MainWindow* mainWindow) {
+ m_mainWindow = mainWindow;
+}
+
+/// @brief Adds the Theme to the list of themes
+/// @param theme The Theme to add
+/// @return Theme ID
+QString ThemeManager::AddTheme(ITheme * theme) {
+ m_themes.insert(std::make_pair(theme->id(), std::unique_ptr<ITheme>(theme)));
+ return theme->id();
+}
+
+/// @brief Gets the Theme from the List via ID
+/// @param themeId Theme ID of theme to fetch
+/// @return Theme at themeId
+ITheme* ThemeManager::GetTheme(QString themeId) {
+ return m_themes[themeId].get();
+}
+
+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.";
+ }
+
+ // Initialize widget themes
+ {
+ themeDebugLog << "<> Initializing Widget Themes";
+ themeDebugLog "✓ Loading Built-in Theme:" << AddTheme(new SystemTheme());
+ auto darkThemeId = AddTheme(new DarkTheme());
+ themeDebugLog "✓ Loading Built-in Theme:" << darkThemeId;
+ themeDebugLog "✓ Loading Built-in Theme:" << AddTheme(new BrightTheme());
+
+ // TODO: need some way to differentiate same name themes in different subdirectories (maybe smaller grey text next to theme name in dropdown? Dunno how to do that though)
+ QString themeFolder = (new QDir("./themes/"))->absoluteFilePath("");
+ themeDebugLog << "Theme Folder Path: " << themeFolder;
+
+ QDirIterator directoryIterator(themeFolder, QDir::Dirs | QDir::NoDotAndDotDot, QDirIterator::Subdirectories);
+ 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();
+ CustomTheme* theme = new CustomTheme(GetTheme(darkThemeId), themeJson, true);
+ AddTheme(theme);
+ } 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();
+ CustomTheme* theme = new CustomTheme(GetTheme(darkThemeId), customThemeFileInfo, false);
+ AddTheme(theme);
+ }
+ }
+ }
+
+ themeDebugLog << "<> Widget themes initialized.";
+ }
+}
+
+std::vector<ITheme *> ThemeManager::getValidApplicationThemes()
+{
+ std::vector<ITheme *> ret;
+ auto iter = m_themes.cbegin();
+ while (iter != m_themes.cend())
+ {
+ ret.push_back((*iter).second.get());
+ iter++;
+ }
+ return ret;
+}
+
+void ThemeManager::setIconTheme(const QString& name)
+{
+ QIcon::setThemeName(name);
+}
+
+void ThemeManager::applyCurrentlySelectedTheme() {
+ setIconTheme(APPLICATION->settings()->get("IconTheme").toString());
+ themeDebugLog() << "<> Icon theme set.";
+ setApplicationTheme(APPLICATION->settings()->get("ApplicationTheme").toString(), true);
+ themeDebugLog() << "<> Application theme set.";
+}
+
+void ThemeManager::setApplicationTheme(const QString& name, bool initial)
+{
+ auto systemPalette = qApp->palette();
+ auto themeIter = m_themes.find(name);
+ if(themeIter != m_themes.end())
+ {
+ auto & theme = (*themeIter).second;
+ theme->apply(initial);
+#ifdef Q_OS_WIN
+ if (m_mainWindow && IsWindows10OrGreater()) {
+ if (QString::compare(theme->id(), "dark") == 0) {
+ WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), true);
+ } else {
+ WinDarkmode::setDarkWinTitlebar(m_mainWindow->winId(), false);
+ }
+ }
+#endif
+ }
+ else
+ {
+ qWarning() << "Tried to set invalid theme:" << name;
+ }
+}
diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h new file mode 100644 index 00000000..fa6ea236 --- /dev/null +++ b/launcher/ui/themes/ThemeManager.h @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-3.0-only
+/*
+ * Prism Launcher
+ * Copyright (C) 2022 Tayou <tayou@gmx.net>
+ *
+ * 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 <QString>
+
+#include "ui/themes/ITheme.h"
+#include "ui/MainWindow.h"
+
+#define themeDebugLog qDebug() << "[Themes]"
+#define themeWarningLog qWarning() << "[Themes]"
+
+class ThemeManager {
+public:
+ ThemeManager(MainWindow* mainWindow);
+ void InitializeThemes();
+
+ std::vector<ITheme *> getValidApplicationThemes();
+ void setIconTheme(const QString& name);
+ void applyCurrentlySelectedTheme();
+ void setApplicationTheme(const QString& name, bool initial);
+
+private:
+ std::map<QString, std::unique_ptr<ITheme>> m_themes;
+ MainWindow* m_mainWindow;
+
+ QString AddTheme(ITheme * theme);
+ ITheme* GetTheme(QString themeId);
+};
+
|