aboutsummaryrefslogtreecommitdiff
path: root/launcher
diff options
context:
space:
mode:
Diffstat (limited to 'launcher')
-rw-r--r--launcher/Application.cpp51
-rw-r--r--launcher/Application.h13
-rw-r--r--launcher/CMakeLists.txt2
-rw-r--r--launcher/DesktopServices.cpp2
-rw-r--r--launcher/resources/multimc/index.theme2
-rw-r--r--launcher/resources/pe_blue/index.theme2
-rw-r--r--launcher/resources/pe_colored/index.theme2
-rw-r--r--launcher/resources/pe_dark/index.theme2
-rw-r--r--launcher/resources/pe_light/index.theme2
-rw-r--r--launcher/ui/MainWindow.cpp32
-rw-r--r--launcher/ui/MainWindow.h9
-rw-r--r--launcher/ui/MainWindow.ui57
-rw-r--r--launcher/ui/instanceview/InstanceView.cpp4
-rw-r--r--launcher/ui/setupwizard/ThemeWizardPage.cpp2
-rw-r--r--launcher/ui/themes/IconTheme.cpp53
-rw-r--r--launcher/ui/themes/IconTheme.h37
-rw-r--r--launcher/ui/themes/ThemeManager.cpp192
-rw-r--r--launcher/ui/themes/ThemeManager.h23
-rw-r--r--launcher/ui/widgets/ThemeCustomizationWidget.cpp55
-rw-r--r--launcher/ui/widgets/ThemeCustomizationWidget.h16
-rw-r--r--launcher/ui/widgets/ThemeCustomizationWidget.ui98
21 files changed, 461 insertions, 195 deletions
diff --git a/launcher/Application.cpp b/launcher/Application.cpp
index aeea90f1..acac2da2 100644
--- a/launcher/Application.cpp
+++ b/launcher/Application.cpp
@@ -526,7 +526,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
m_settings.reset(new INISettingsObject({ BuildConfig.LAUNCHER_CONFIGFILE, "polymc.cfg", "multimc.cfg" }, this));
// Theming
- m_settings->registerSetting("IconTheme", QString("pe_colored"));
+ m_settings->registerSetting("IconTheme", QString());
m_settings->registerSetting("ApplicationTheme", QString());
m_settings->registerSetting("BackgroundCat", QString("kitteh"));
@@ -801,7 +801,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
}
// Themes
- m_themeManager = std::make_unique<ThemeManager>(m_mainWindow);
+ m_themeManager = std::make_unique<ThemeManager>();
// initialize and load all instances
{
@@ -893,8 +893,6 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
}
});
- applyCurrentlySelectedTheme(true);
-
updateCapabilities();
if(createSetupWizard())
@@ -902,6 +900,7 @@ Application::Application(int &argc, char **argv) : QApplication(argc, argv)
return;
}
+ m_themeManager->applyCurrentlySelectedTheme(true);
performMainStartupAction();
}
@@ -930,11 +929,21 @@ bool Application::createSetupWizard()
}();
bool languageRequired = settings()->get("Language").toString().isEmpty();
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;
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);
if (languageRequired)
{
@@ -953,9 +962,9 @@ bool Application::createSetupWizard()
if (themeInterventionRequired)
{
- settings()->set("ApplicationTheme", QString("system")); // set default theme after going into theme wizard
m_setupWizard->addPage(new ThemeWizardPage(m_setupWizard));
}
+
connect(m_setupWizard, &QDialog::finished, this, &Application::setupWizardFinished);
m_setupWizard->show();
return true;
@@ -1158,26 +1167,6 @@ std::shared_ptr<JavaInstallList> Application::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)
{
if(name == "logo") {
@@ -1186,16 +1175,6 @@ QIcon Application::getThemedIcon(const QString& 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)
{
const QString file = QDir::current().absoluteFilePath(filename);
diff --git a/launcher/Application.h b/launcher/Application.h
index c0a980b2..1c221cec 100644
--- a/launcher/Application.h
+++ b/launcher/Application.h
@@ -71,6 +71,7 @@ class TranslationsModel;
class ITheme;
class MCEditTool;
class ThemeManager;
+class IconTheme;
namespace Meta {
class Index;
@@ -119,17 +120,7 @@ public:
QIcon getThemedIcon(const QString& name);
- void setIconTheme(const QString& name);
-
- void applyCurrentlySelectedTheme(bool initial = false);
-
- QList<ITheme*> getValidApplicationThemes();
-
- void setApplicationTheme(const QString& name);
-
- QList<CatPack*> getValidCatPacks();
-
- QString getCatPack(QString catName = "");
+ ThemeManager* themeManager() { return m_themeManager.get(); }
shared_qobject_ptr<ExternalUpdater> updater() { return m_updater; }
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 2d06dbf4..8f5b0e77 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -759,6 +759,8 @@ SET(LAUNCHER_SOURCES
ui/themes/ITheme.h
ui/themes/SystemTheme.cpp
ui/themes/SystemTheme.h
+ ui/themes/IconTheme.cpp
+ ui/themes/IconTheme.h
ui/themes/ThemeManager.cpp
ui/themes/ThemeManager.h
ui/themes/CatPack.cpp
diff --git a/launcher/DesktopServices.cpp b/launcher/DesktopServices.cpp
index 2984a1b4..4939161f 100644
--- a/launcher/DesktopServices.cpp
+++ b/launcher/DesktopServices.cpp
@@ -109,7 +109,7 @@ bool openDirectory(const QString &path, bool ensureExists)
qDebug() << "Opening directory" << path;
QDir parentPath;
QDir dir(path);
- if (!dir.exists())
+ if (ensureExists && !dir.exists())
{
parentPath.mkpath(dir.absolutePath());
}
diff --git a/launcher/resources/multimc/index.theme b/launcher/resources/multimc/index.theme
index 070e23f1..4da8072d 100644
--- a/launcher/resources/multimc/index.theme
+++ b/launcher/resources/multimc/index.theme
@@ -1,5 +1,5 @@
[Icon Theme]
-Name=multimc
+Name=Legacy
Comment=Default Icons
Inherits=default
Directories=8x8,16x16,22x22,24x24,32x32,32x32/instances,48x48,50x50/instances,64x64,128x128/instances,256x256,scalable,scalable/instances
diff --git a/launcher/resources/pe_blue/index.theme b/launcher/resources/pe_blue/index.theme
index c9e0d93a..6d842b5d 100644
--- a/launcher/resources/pe_blue/index.theme
+++ b/launcher/resources/pe_blue/index.theme
@@ -1,5 +1,5 @@
[Icon Theme]
-Name=pe_blue
+Name=Simple (Blue)
Comment=Icons by pexner (blue)
Inherits=multimc
Directories=scalable
diff --git a/launcher/resources/pe_colored/index.theme b/launcher/resources/pe_colored/index.theme
index b757bbd7..bca5494f 100644
--- a/launcher/resources/pe_colored/index.theme
+++ b/launcher/resources/pe_colored/index.theme
@@ -1,5 +1,5 @@
[Icon Theme]
-Name=pe_colored
+Name=Simple (Colored)
Comment=Icons by pexner (colored)
Inherits=multimc
Directories=scalable
diff --git a/launcher/resources/pe_dark/index.theme b/launcher/resources/pe_dark/index.theme
index b7d1ad01..4cfbf09c 100644
--- a/launcher/resources/pe_dark/index.theme
+++ b/launcher/resources/pe_dark/index.theme
@@ -1,5 +1,5 @@
[Icon Theme]
-Name=pe_dark
+Name=Simple (Dark)
Comment=Icons by pexner (dark)
Inherits=multimc
Directories=scalable
diff --git a/launcher/resources/pe_light/index.theme b/launcher/resources/pe_light/index.theme
index c106acc8..87b76d13 100644
--- a/launcher/resources/pe_light/index.theme
+++ b/launcher/resources/pe_light/index.theme
@@ -1,5 +1,5 @@
[Icon Theme]
-Name=pe_light
+Name=Simple (Light)
Comment=Icons by pexner (light)
Inherits=multimc
Directories=scalable
diff --git a/launcher/ui/MainWindow.cpp b/launcher/ui/MainWindow.cpp
index da572fc3..e4a699da 100644
--- a/launcher/ui/MainWindow.cpp
+++ b/launcher/ui/MainWindow.cpp
@@ -627,7 +627,7 @@ void MainWindow::updateThemeMenu()
themeMenu = new QMenu(this);
}
- auto themes = APPLICATION->getValidApplicationThemes();
+ auto themes = APPLICATION->themeManager()->getValidApplicationThemes();
QActionGroup* themesGroup = new QActionGroup(this);
@@ -641,7 +641,7 @@ void MainWindow::updateThemeMenu()
themeAction->setActionGroup(themesGroup);
connect(themeAction, &QAction::triggered, [theme]() {
- APPLICATION->setApplicationTheme(theme->id());
+ APPLICATION->themeManager()->setApplicationTheme(theme->id());
APPLICATION->settings()->set("ApplicationTheme", theme->id());
});
}
@@ -1134,26 +1134,40 @@ void MainWindow::undoTrashInstance()
ui->actionUndoTrashInstance->setEnabled(APPLICATION->instances()->trashedSomething());
}
+void MainWindow::on_actionViewLauncherRootFolder_triggered()
+{
+ DesktopServices::openDirectory(".");
+}
+
void MainWindow::on_actionViewInstanceFolder_triggered()
{
QString str = APPLICATION->settings()->get("InstanceDir").toString();
DesktopServices::openDirectory(str);
}
-void MainWindow::on_actionViewLauncherRootFolder_triggered()
+void MainWindow::on_actionViewCentralModsFolder_triggered()
{
- const QString dataPath = QDir::currentPath();
- DesktopServices::openDirectory(dataPath);
+ DesktopServices::openDirectory(APPLICATION->settings()->get("CentralModsDir").toString(), true);
}
-void MainWindow::refreshInstances()
+void MainWindow::on_actionViewIconThemeFolder_triggered()
{
- APPLICATION->instances()->loadList();
+ DesktopServices::openDirectory(APPLICATION->themeManager()->getIconThemesFolder().path());
}
-void MainWindow::on_actionViewCentralModsFolder_triggered()
+void MainWindow::on_actionViewWidgetThemeFolder_triggered()
{
- DesktopServices::openDirectory(APPLICATION->settings()->get("CentralModsDir").toString(), true);
+ DesktopServices::openDirectory(APPLICATION->themeManager()->getApplicationThemesFolder().path());
+}
+
+void MainWindow::on_actionViewCatPackFolder_triggered()
+{
+ DesktopServices::openDirectory(APPLICATION->themeManager()->getCatPacksFolder().path());
+}
+
+void MainWindow::refreshInstances()
+{
+ APPLICATION->instances()->loadList();
}
void MainWindow::checkForUpdates()
diff --git a/launcher/ui/MainWindow.h b/launcher/ui/MainWindow.h
index 27c2756f..ffc7154a 100644
--- a/launcher/ui/MainWindow.h
+++ b/launcher/ui/MainWindow.h
@@ -111,16 +111,19 @@ private slots:
void on_actionChangeInstIcon_triggered();
+ void on_actionViewLauncherRootFolder_triggered();
+
void on_actionViewInstanceFolder_triggered();
+ void on_actionViewCentralModsFolder_triggered();
- void on_actionViewLauncherRootFolder_triggered();
+ void on_actionViewIconThemeFolder_triggered();
+ void on_actionViewWidgetThemeFolder_triggered();
+ void on_actionViewCatPackFolder_triggered();
void on_actionViewSelectedInstFolder_triggered();
void refreshInstances();
- void on_actionViewCentralModsFolder_triggered();
-
void checkForUpdates();
void on_actionSettings_triggered();
diff --git a/launcher/ui/MainWindow.ui b/launcher/ui/MainWindow.ui
index e4421d40..6ef32099 100644
--- a/launcher/ui/MainWindow.ui
+++ b/launcher/ui/MainWindow.ui
@@ -186,9 +186,14 @@
<property name="toolTipsVisible">
<bool>true</bool>
</property>
- <addaction name="actionViewInstanceFolder"/>
<addaction name="actionViewLauncherRootFolder"/>
+ <addaction name="separator"/>
+ <addaction name="actionViewInstanceFolder"/>
<addaction name="actionViewCentralModsFolder"/>
+ <addaction name="separator"/>
+ <addaction name="actionViewIconThemeFolder"/>
+ <addaction name="actionViewWidgetThemeFolder"/>
+ <addaction name="actionViewCatPackFolder"/>
</widget>
<widget class="QMenu" name="accountsMenu">
<property name="title">
@@ -465,7 +470,8 @@
</action>
<action name="actionExportInstanceZip">
<property name="icon">
- <iconset theme="launcher"/>
+ <iconset theme="launcher">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Prism Launcher (zip)</string>
@@ -473,7 +479,8 @@
</action>
<action name="actionExportInstanceMrPack">
<property name="icon">
- <iconset theme="modrinth"/>
+ <iconset theme="modrinth">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Modrinth (mrpack)</string>
@@ -481,15 +488,17 @@
</action>
<action name="actionExportInstanceFlamePack">
<property name="icon">
- <iconset theme="flame"/>
+ <iconset theme="flame">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
- <string>CurseForge (zip)</string>
+ <string>CurseForge (zip)</string>
</property>
</action>
<action name="actionExportInstanceToModList">
<property name="icon">
- <iconset theme="new"/>
+ <iconset theme="new">
+ <normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>Mod List</string>
@@ -552,7 +561,7 @@
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
- <string>&amp;View Instance Folder</string>
+ <string>View &amp;Instance Folder</string>
</property>
<property name="toolTip">
<string>Open the instance folder in a file browser.</string>
@@ -564,7 +573,7 @@
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
- <string>&amp;View Launcher Root Folder</string>
+ <string>View Launcher &amp;Root Folder</string>
</property>
<property name="toolTip">
<string>Open the launcher's root folder in a file browser.</string>
@@ -719,6 +728,38 @@
<string>Open the %1 wiki</string>
</property>
</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>
<customwidgets>
<customwidget>
diff --git a/launcher/ui/instanceview/InstanceView.cpp b/launcher/ui/instanceview/InstanceView.cpp
index 05f0004d..155550e1 100644
--- a/launcher/ui/instanceview/InstanceView.cpp
+++ b/launcher/ui/instanceview/InstanceView.cpp
@@ -52,7 +52,7 @@
#include <Application.h>
#include <InstanceList.h>
-
+#include "ui/themes/ThemeManager.h"
template <typename T> bool listsIntersect(const QList<T> &l1, const QList<T> t2)
{
@@ -503,7 +503,7 @@ void InstanceView::setPaintCat(bool visible)
{
m_catVisible = visible;
if (visible)
- m_catPixmap.load(APPLICATION->getCatPack());
+ m_catPixmap.load(APPLICATION->themeManager()->getCatPack());
else
m_catPixmap = QPixmap();
}
diff --git a/launcher/ui/setupwizard/ThemeWizardPage.cpp b/launcher/ui/setupwizard/ThemeWizardPage.cpp
index 1c336921..fe11ed9a 100644
--- a/launcher/ui/setupwizard/ThemeWizardPage.cpp
+++ b/launcher/ui/setupwizard/ThemeWizardPage.cpp
@@ -61,7 +61,7 @@ void ThemeWizardPage::updateIcons()
void ThemeWizardPage::updateCat()
{
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()
diff --git a/launcher/ui/themes/IconTheme.cpp b/launcher/ui/themes/IconTheme.cpp
new file mode 100644
index 00000000..4bd88985
--- /dev/null
+++ b/launcher/ui/themes/IconTheme.cpp
@@ -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;
+}
diff --git a/launcher/ui/themes/IconTheme.h b/launcher/ui/themes/IconTheme.h
new file mode 100644
index 00000000..4e466c6a
--- /dev/null
+++ b/launcher/ui/themes/IconTheme.h
@@ -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;
+};
diff --git a/launcher/ui/themes/ThemeManager.cpp b/launcher/ui/themes/ThemeManager.cpp
index 321f7db4..bce13b45 100644
--- a/launcher/ui/themes/ThemeManager.cpp
+++ b/launcher/ui/themes/ThemeManager.cpp
@@ -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>());
-
- // 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;
-
- 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));
- }
+ 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() << "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.";
+ 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 theme 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"));
diff --git a/launcher/ui/themes/ThemeManager.h b/launcher/ui/themes/ThemeManager.h
index 1ce8c6f4..b5c66677 100644
--- a/launcher/ui/themes/ThemeManager.h
+++ b/launcher/ui/themes/ThemeManager.h
@@ -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" };
};
diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.cpp b/launcher/ui/widgets/ThemeCustomizationWidget.cpp
index 291f8ed9..c999ac92 100644
--- a/launcher/ui/widgets/ThemeCustomizationWidget.cpp
+++ b/launcher/ui/widgets/ThemeCustomizationWidget.cpp
@@ -19,17 +19,23 @@
#include "ui_ThemeCustomizationWidget.h"
#include "Application.h"
+#include "DesktopServices.h"
#include "ui/themes/ITheme.h"
#include "ui/themes/ThemeManager.h"
-ThemeCustomizationWidget::ThemeCustomizationWidget(QWidget *parent) : QWidget(parent), ui(new Ui::ThemeCustomizationWidget)
+ThemeCustomizationWidget::ThemeCustomizationWidget(QWidget* parent) : QWidget(parent), ui(new Ui::ThemeCustomizationWidget)
{
ui->setupUi(this);
loadSettings();
connect(ui->iconsComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ThemeCustomizationWidget::applyIconTheme);
- connect(ui->widgetStyleComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ThemeCustomizationWidget::applyWidgetTheme);
+ connect(ui->widgetStyleComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
+ &ThemeCustomizationWidget::applyWidgetTheme);
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()
@@ -40,7 +46,7 @@ ThemeCustomizationWidget::~ThemeCustomizationWidget()
/// <summary>
/// The layout was not quite right, so currently this just disables the UI elements, which should be hidden instead
/// TODO FIXME
-///
+///
/// Original Method One:
/// ui->iconsComboBox->setVisible(features& ThemeFields::ICONS);
/// ui->iconsLabel->setVisible(features& ThemeFields::ICONS);
@@ -48,7 +54,7 @@ ThemeCustomizationWidget::~ThemeCustomizationWidget()
/// ui->widgetThemeLabel->setVisible(features& ThemeFields::WIDGETS);
/// ui->backgroundCatComboBox->setVisible(features& ThemeFields::CAT);
/// ui->backgroundCatLabel->setVisible(features& ThemeFields::CAT);
-///
+///
/// original Method Two:
/// if (!(features & ThemeFields::ICONS)) {
/// ui->formLayout->setRowVisible(0, false);
@@ -61,35 +67,37 @@ ThemeCustomizationWidget::~ThemeCustomizationWidget()
/// }
/// </summary>
/// <param name="features"></param>
-void ThemeCustomizationWidget::showFeatures(ThemeFields features) {
+void ThemeCustomizationWidget::showFeatures(ThemeFields features)
+{
ui->iconsComboBox->setEnabled(features & ThemeFields::ICONS);
ui->iconsLabel->setEnabled(features & ThemeFields::ICONS);
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->backgroundCatLabel->setEnabled(features & ThemeFields::CAT);
}
-void ThemeCustomizationWidget::applyIconTheme(int index) {
+void ThemeCustomizationWidget::applyIconTheme(int index)
+{
auto settings = APPLICATION->settings();
auto originalIconTheme = settings->get("IconTheme").toString();
- auto& newIconTheme = m_iconThemeOptions[index].first;
- settings->set("IconTheme", newIconTheme);
-
+ auto newIconTheme = ui->iconsComboBox->currentData().toString();
if (originalIconTheme != newIconTheme) {
- APPLICATION->applyCurrentlySelectedTheme();
+ settings->set("IconTheme", newIconTheme);
+ APPLICATION->themeManager()->applyCurrentlySelectedTheme();
}
emit currentIconThemeChanged(index);
}
-void ThemeCustomizationWidget::applyWidgetTheme(int index) {
+void ThemeCustomizationWidget::applyWidgetTheme(int index)
+{
auto settings = APPLICATION->settings();
auto originalAppTheme = settings->get("ApplicationTheme").toString();
auto newAppTheme = ui->widgetStyleComboBox->currentData().toString();
if (originalAppTheme != newAppTheme) {
settings->set("ApplicationTheme", newAppTheme);
- APPLICATION->applyCurrentlySelectedTheme();
+ APPLICATION->themeManager()->applyCurrentlySelectedTheme();
}
emit currentWidgetThemeChanged(index);
@@ -117,18 +125,23 @@ void ThemeCustomizationWidget::loadSettings()
{
auto settings = APPLICATION->settings();
- auto iconTheme = settings->get("IconTheme").toString();
- for (auto& iconThemeFromList : m_iconThemeOptions) {
- QIcon iconForComboBox = QIcon(QString(":/icons/%1/scalable/settings").arg(iconThemeFromList.first));
- ui->iconsComboBox->addItem(iconForComboBox, iconThemeFromList.second);
- if (iconTheme == iconThemeFromList.first) {
- ui->iconsComboBox->setCurrentIndex(ui->iconsComboBox->count() - 1);
+ {
+ auto currentIconTheme = settings->get("IconTheme").toString();
+ auto iconThemes = APPLICATION->themeManager()->getValidIconThemes();
+ int idx = 0;
+ for (auto iconTheme : iconThemes) {
+ 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 themes = APPLICATION->getValidApplicationThemes();
+ auto themes = APPLICATION->themeManager()->getValidApplicationThemes();
int idx = 0;
for (auto& theme : themes) {
ui->widgetStyleComboBox->addItem(theme->name(), theme->id());
@@ -140,7 +153,7 @@ void ThemeCustomizationWidget::loadSettings()
}
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()));
ui->backgroundCatComboBox->addItem(catIcon, catFromList->name(), catFromList->id());
if (cat == catFromList->id()) {
diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.h b/launcher/ui/widgets/ThemeCustomizationWidget.h
index af47c788..cef5fb6c 100644
--- a/launcher/ui/widgets/ThemeCustomizationWidget.h
+++ b/launcher/ui/widgets/ThemeCustomizationWidget.h
@@ -31,7 +31,7 @@ class ThemeCustomizationWidget : public QWidget {
public:
explicit ThemeCustomizationWidget(QWidget* parent = nullptr);
- ~ThemeCustomizationWidget();
+ ~ThemeCustomizationWidget() override;
void showFeatures(ThemeFields features);
@@ -52,18 +52,4 @@ class ThemeCustomizationWidget : public QWidget {
private:
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") } };
};
diff --git a/launcher/ui/widgets/ThemeCustomizationWidget.ui b/launcher/ui/widgets/ThemeCustomizationWidget.ui
index f216a610..4503181c 100644
--- a/launcher/ui/widgets/ThemeCustomizationWidget.ui
+++ b/launcher/ui/widgets/ThemeCustomizationWidget.ui
@@ -40,22 +40,43 @@
</widget>
</item>
<item row="0" column="1">
- <widget class="QComboBox" name="iconsComboBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="focusPolicy">
- <enum>Qt::StrongFocus</enum>
- </property>
- </widget>
+ <layout class="QHBoxLayout" name="iconsLayout">
+ <item>
+ <widget class="QComboBox" name="iconsComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="iconsFolder">
+ <property name="toolTip">
+ <string>View icon 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="1" column="0">
- <widget class="QLabel" name="widgetThemeLabel">
+ <widget class="QLabel" name="widgetStyleLabel">
<property name="text">
- <string>&amp;Colors</string>
+ <string>&amp;Widgets</string>
</property>
<property name="buddy">
<cstring>widgetStyleComboBox</cstring>
@@ -63,17 +84,38 @@
</widget>
</item>
<item row="1" column="1">
- <widget class="QComboBox" name="widgetStyleComboBox">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="focusPolicy">
- <enum>Qt::StrongFocus</enum>
- </property>
- </widget>
+ <layout class="QHBoxLayout" name="widgetStyleLayout">
+ <item>
+ <widget class="QComboBox" name="widgetStyleComboBox">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="focusPolicy">
+ <enum>Qt::StrongFocus</enum>
+ </property>
+ </widget>
+ </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">
<widget class="QLabel" name="backgroundCatLabel">
@@ -89,7 +131,7 @@
</widget>
</item>
<item row="2" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout">
+ <layout class="QHBoxLayout" name="catLayout">
<item>
<widget class="QComboBox" name="backgroundCatComboBox">
<property name="sizePolicy">
@@ -107,15 +149,15 @@
</widget>
</item>
<item>
- <widget class="QPushButton" name="catInfoLabel">
+ <widget class="QPushButton" name="catPackFolder">
<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 name="text">
<string/>
</property>
<property name="icon">
- <iconset theme="about">
+ <iconset theme="viewfolder">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="flat">