|
@@ -9,7 +9,9 @@
|
|
|
#include <fstream>
|
|
#include <fstream>
|
|
|
#include <iostream>
|
|
#include <iostream>
|
|
|
#include <memory>
|
|
#include <memory>
|
|
|
|
|
+#include <QStyleFactory>
|
|
|
#include <thread>
|
|
#include <thread>
|
|
|
|
|
+
|
|
|
#include "core/hle/service/am/applet_manager.h"
|
|
#include "core/hle/service/am/applet_manager.h"
|
|
|
#include "core/loader/nca.h"
|
|
#include "core/loader/nca.h"
|
|
|
#include "core/loader/nro.h"
|
|
#include "core/loader/nro.h"
|
|
@@ -20,6 +22,9 @@
|
|
|
#endif
|
|
#endif
|
|
|
#ifdef __unix__
|
|
#ifdef __unix__
|
|
|
#include <csignal>
|
|
#include <csignal>
|
|
|
|
|
+#include <QtDBus/QDBusInterface>
|
|
|
|
|
+#include <QtDBus/QDBusMessage>
|
|
|
|
|
+#include <QtDBus/QtDBus>
|
|
|
#include <sys/socket.h>
|
|
#include <sys/socket.h>
|
|
|
#include "common/linux/gamemode.h"
|
|
#include "common/linux/gamemode.h"
|
|
|
#endif
|
|
#endif
|
|
@@ -271,18 +276,6 @@ static void OverrideWindowsFont() {
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
-bool GMainWindow::CheckDarkMode() {
|
|
|
|
|
-#ifdef __unix__
|
|
|
|
|
- const QPalette test_palette(qApp->palette());
|
|
|
|
|
- const QColor text_color = test_palette.color(QPalette::Active, QPalette::Text);
|
|
|
|
|
- const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
|
|
|
|
|
- return (text_color.value() > window_color.value());
|
|
|
|
|
-#else
|
|
|
|
|
- // TODO: Windows
|
|
|
|
|
- return false;
|
|
|
|
|
-#endif // __unix__
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan)
|
|
GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulkan)
|
|
|
: ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()},
|
|
: ui{std::make_unique<Ui::MainWindow>()}, system{std::make_unique<Core::System>()},
|
|
|
input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, config{std::move(config_)},
|
|
input_subsystem{std::make_shared<InputCommon::InputSubsystem>()}, config{std::move(config_)},
|
|
@@ -303,8 +296,6 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
|
|
|
ui->setupUi(this);
|
|
ui->setupUi(this);
|
|
|
statusBar()->hide();
|
|
statusBar()->hide();
|
|
|
|
|
|
|
|
- // Check dark mode before a theme is loaded
|
|
|
|
|
- os_dark_mode = CheckDarkMode();
|
|
|
|
|
startup_icon_theme = QIcon::themeName();
|
|
startup_icon_theme = QIcon::themeName();
|
|
|
// fallback can only be set once, colorful theme icons are okay on both light/dark
|
|
// fallback can only be set once, colorful theme icons are okay on both light/dark
|
|
|
QIcon::setFallbackThemeName(QStringLiteral("colorful"));
|
|
QIcon::setFallbackThemeName(QStringLiteral("colorful"));
|
|
@@ -329,6 +320,7 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
|
|
|
|
|
|
|
|
SetDefaultUIGeometry();
|
|
SetDefaultUIGeometry();
|
|
|
RestoreUIState();
|
|
RestoreUIState();
|
|
|
|
|
+ UpdateUITheme();
|
|
|
|
|
|
|
|
ConnectMenuEvents();
|
|
ConnectMenuEvents();
|
|
|
ConnectWidgetEvents();
|
|
ConnectWidgetEvents();
|
|
@@ -449,7 +441,10 @@ GMainWindow::GMainWindow(std::unique_ptr<QtConfig> config_, bool has_broken_vulk
|
|
|
SDL_EnableScreenSaver();
|
|
SDL_EnableScreenSaver();
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+#ifdef __unix__
|
|
|
SetupPrepareForSleep();
|
|
SetupPrepareForSleep();
|
|
|
|
|
+ ListenColorSchemeChange();
|
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
QStringList args = QApplication::arguments();
|
|
QStringList args = QApplication::arguments();
|
|
|
|
|
|
|
@@ -1647,8 +1642,8 @@ void GMainWindow::OnDisplayTitleBars(bool show) {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void GMainWindow::SetupPrepareForSleep() {
|
|
|
|
|
#ifdef __unix__
|
|
#ifdef __unix__
|
|
|
|
|
+void GMainWindow::SetupPrepareForSleep() {
|
|
|
auto bus = QDBusConnection::systemBus();
|
|
auto bus = QDBusConnection::systemBus();
|
|
|
if (bus.isConnected()) {
|
|
if (bus.isConnected()) {
|
|
|
const bool success = bus.connect(
|
|
const bool success = bus.connect(
|
|
@@ -1662,8 +1657,8 @@ void GMainWindow::SetupPrepareForSleep() {
|
|
|
} else {
|
|
} else {
|
|
|
LOG_WARNING(Frontend, "QDBusConnection system bus is not connected");
|
|
LOG_WARNING(Frontend, "QDBusConnection system bus is not connected");
|
|
|
}
|
|
}
|
|
|
-#endif // __unix__
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+#endif // __unix__
|
|
|
|
|
|
|
|
void GMainWindow::OnPrepareForSleep(bool prepare_sleep) {
|
|
void GMainWindow::OnPrepareForSleep(bool prepare_sleep) {
|
|
|
if (emu_thread == nullptr) {
|
|
if (emu_thread == nullptr) {
|
|
@@ -4799,9 +4794,106 @@ void GMainWindow::filterBarSetChecked(bool state) {
|
|
|
emit(OnToggleFilterBar());
|
|
emit(OnToggleFilterBar());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+void GMainWindow::UpdateUITheme() {
|
|
|
|
|
+ LOG_DEBUG(Frontend, "Updating UI");
|
|
|
|
|
+ QString default_theme = QString::fromStdString(UISettings::default_theme.data());
|
|
|
|
|
+ QString current_theme = UISettings::values.theme;
|
|
|
|
|
+ if (current_theme.isEmpty()) {
|
|
|
|
|
+ current_theme = default_theme;
|
|
|
|
|
+ }
|
|
|
|
|
+ const bool current_dark_mode = CheckDarkMode();
|
|
|
|
|
+
|
|
|
|
|
+ UpdateIcons(current_theme);
|
|
|
|
|
+
|
|
|
|
|
+ /* Find the stylesheet to load */
|
|
|
|
|
+ if (TryLoadStylesheet(current_theme)) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Reading new theme failed, loading default stylesheet
|
|
|
|
|
+ LOG_ERROR(Frontend, "Unable to open style \"{}\", fallback to the default theme",
|
|
|
|
|
+ current_theme.toStdString());
|
|
|
|
|
+
|
|
|
|
|
+ if (TryLoadStylesheet(QStringLiteral(":/%1").arg(default_theme))) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Reading default failed, loading empty stylesheet
|
|
|
|
|
+ LOG_ERROR(Frontend, "Unable to set default style, stylesheet file not found");
|
|
|
|
|
+
|
|
|
|
|
+ qApp->setStyleSheet({});
|
|
|
|
|
+ setStyleSheet({});
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void GMainWindow::UpdateIcons(const QString& theme_path) {
|
|
|
|
|
+ // Get the theme directory from its path
|
|
|
|
|
+ std::size_t last_slash = theme_path.toStdString().find_last_of("/");
|
|
|
|
|
+ QString theme_dir = QString::fromStdString(theme_path.toStdString().substr(last_slash + 1));
|
|
|
|
|
+
|
|
|
|
|
+ // Append _dark to the theme name to use dark variant icons
|
|
|
|
|
+ if (CheckDarkMode()) {
|
|
|
|
|
+ LOG_DEBUG(Frontend, "Using icons from: {}", theme_dir.toStdString() + "_dark");
|
|
|
|
|
+ QIcon::setThemeName(theme_dir + QStringLiteral("_dark"));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ LOG_DEBUG(Frontend, "Using icons from: {}", theme_dir.toStdString());
|
|
|
|
|
+ QIcon::setThemeName(theme_dir);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const QString theme_directory{
|
|
|
|
|
+ QString::fromStdString(Common::FS::GetSuyuPathString(Common::FS::SuyuPath::ThemesDir))};
|
|
|
|
|
+
|
|
|
|
|
+ // Set path for default icons
|
|
|
|
|
+ // Use icon resources from application binary and current theme local subdirectory, if it exists
|
|
|
|
|
+ QStringList theme_paths;
|
|
|
|
|
+ theme_paths << QString::fromStdString(":/icons") << QStringLiteral("%1").arg(theme_directory);
|
|
|
|
|
+ QIcon::setThemeSearchPaths(theme_paths);
|
|
|
|
|
+
|
|
|
|
|
+ // Change current directory, to allow user themes to add their own icons
|
|
|
|
|
+ QDir::setCurrent(QStringLiteral("%1/%2").arg(theme_directory, UISettings::values.theme));
|
|
|
|
|
+
|
|
|
|
|
+ emit UpdateThemedIcons();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool GMainWindow::TryLoadStylesheet(const QString& theme_uri) {
|
|
|
|
|
+ QString style_path;
|
|
|
|
|
+
|
|
|
|
|
+ // Use themed stylesheet if it exists
|
|
|
|
|
+ if (CheckDarkMode()) {
|
|
|
|
|
+ style_path = theme_uri + QStringLiteral("/dark.qss");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ style_path = theme_uri + QStringLiteral("/light.qss");
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!QFile::exists(style_path)) {
|
|
|
|
|
+ LOG_INFO(Frontend, "Themed (light/dark) stylesheet could not be found, using default one");
|
|
|
|
|
+ // Use common stylesheet if themed one does not exist
|
|
|
|
|
+ style_path = theme_uri + QStringLiteral("/style.qss");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Loading stylesheet
|
|
|
|
|
+ QFile style_file(style_path);
|
|
|
|
|
+ if (style_file.open(QFile::ReadOnly | QFile::Text)) {
|
|
|
|
|
+ // Update the color palette before applying the stylesheet
|
|
|
|
|
+ UpdateThemePalette();
|
|
|
|
|
+
|
|
|
|
|
+ LOG_INFO(Frontend, "Loading stylesheet in: {}", theme_uri.toStdString());
|
|
|
|
|
+ QTextStream ts_theme(&style_file);
|
|
|
|
|
+ qApp->setStyleSheet(ts_theme.readAll());
|
|
|
|
|
+ setStyleSheet(ts_theme.readAll());
|
|
|
|
|
+ SetCustomStylesheet();
|
|
|
|
|
+
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ // Opening the file failed
|
|
|
|
|
+ return false;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+bool GMainWindow::TryLoadStylesheet(const std::filesystem::path& theme_path) {
|
|
|
|
|
+ return TryLoadStylesheet(QString::fromStdString(theme_path.string() + "/"));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
static void AdjustLinkColor() {
|
|
static void AdjustLinkColor() {
|
|
|
QPalette new_pal(qApp->palette());
|
|
QPalette new_pal(qApp->palette());
|
|
|
- if (UISettings::IsDarkTheme()) {
|
|
|
|
|
|
|
+ if (GMainWindow::CheckDarkMode()) {
|
|
|
new_pal.setColor(QPalette::Link, QColor(0, 190, 255, 255));
|
|
new_pal.setColor(QPalette::Link, QColor(0, 190, 255, 255));
|
|
|
} else {
|
|
} else {
|
|
|
new_pal.setColor(QPalette::Link, QColor(0, 140, 200, 255));
|
|
new_pal.setColor(QPalette::Link, QColor(0, 140, 200, 255));
|
|
@@ -4811,77 +4903,201 @@ static void AdjustLinkColor() {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-void GMainWindow::UpdateUITheme() {
|
|
|
|
|
- QString default_theme = QString::fromStdString(UISettings::default_theme.data());
|
|
|
|
|
- QString current_theme = UISettings::values.theme;
|
|
|
|
|
-
|
|
|
|
|
- if (current_theme.isEmpty()) {
|
|
|
|
|
- current_theme = default_theme;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+void GMainWindow::UpdateThemePalette() {
|
|
|
|
|
+ QPalette themePalette(qApp->palette());
|
|
|
#ifdef _WIN32
|
|
#ifdef _WIN32
|
|
|
- QIcon::setThemeName(current_theme);
|
|
|
|
|
- AdjustLinkColor();
|
|
|
|
|
-#else
|
|
|
|
|
- if (current_theme == QStringLiteral("default") || current_theme == QStringLiteral("colorful")) {
|
|
|
|
|
- LOG_INFO(Frontend, "Theme is default or colorful: {}", current_theme.toStdString());
|
|
|
|
|
- QIcon::setThemeName(current_theme == QStringLiteral("colorful") ? current_theme
|
|
|
|
|
- : startup_icon_theme);
|
|
|
|
|
- QIcon::setThemeSearchPaths(QStringList(default_theme_paths));
|
|
|
|
|
- if (CheckDarkMode()) {
|
|
|
|
|
- current_theme = QStringLiteral("default_dark");
|
|
|
|
|
|
|
+ QColor dark(25, 25, 25);
|
|
|
|
|
+ QColor darkGray(100, 100, 100);
|
|
|
|
|
+ QColor gray(150, 150, 150);
|
|
|
|
|
+ QColor light(230, 230, 230);
|
|
|
|
|
+ // By default, revert fusion style set for Windows dark theme
|
|
|
|
|
+ QString style;
|
|
|
|
|
+ if (CheckDarkMode()) {
|
|
|
|
|
+ // AlternateBase is kept at rgb(233, 231, 227) or rgb(245, 245, 245) on Windows dark
|
|
|
|
|
+ // palette, fix this. Sometimes, it even is rgb(0, 0, 0), but uses a very light gray for
|
|
|
|
|
+ // alternate rows, do not know why
|
|
|
|
|
+ if (themePalette.alternateBase().color() == QColor(233, 231, 227) ||
|
|
|
|
|
+ themePalette.alternateBase().color() == QColor(245, 245, 245) ||
|
|
|
|
|
+ themePalette.alternateBase().color() == QColor(0, 0, 0)) {
|
|
|
|
|
+ themePalette.setColor(QPalette::AlternateBase, dark);
|
|
|
|
|
+ alternate_base_modified = true;
|
|
|
}
|
|
}
|
|
|
|
|
+ // Use fusion theme, since its close to windowsvista, but works well with a dark palette
|
|
|
|
|
+ style = QStringLiteral("fusion");
|
|
|
} else {
|
|
} else {
|
|
|
- LOG_INFO(Frontend, "Theme is NOT default or colorful: {}", current_theme.toStdString());
|
|
|
|
|
- QIcon::setThemeName(current_theme);
|
|
|
|
|
- // Use icon resources from application binary and current theme subdirectory if it exists
|
|
|
|
|
- QStringList theme_paths;
|
|
|
|
|
- theme_paths << QString::fromStdString(":/icons")
|
|
|
|
|
- << QStringLiteral("%1/%2/icons")
|
|
|
|
|
- .arg(QString::fromStdString(
|
|
|
|
|
- Common::FS::GetYuzuPathString(Common::FS::YuzuPath::ThemesDir)),
|
|
|
|
|
- current_theme);
|
|
|
|
|
- QIcon::setThemeSearchPaths(theme_paths);
|
|
|
|
|
- AdjustLinkColor();
|
|
|
|
|
|
|
+ // Reset AlternateBase if it has been modified
|
|
|
|
|
+ if (alternate_base_modified) {
|
|
|
|
|
+ themePalette.setColor(QPalette::AlternateBase, QColor(245, 245, 245));
|
|
|
|
|
+ alternate_base_modified = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ // Reset Windows theme to the default
|
|
|
|
|
+ style = QStringLiteral("windowsvista");
|
|
|
|
|
+ }
|
|
|
|
|
+ LOG_DEBUG(Frontend, "Using style: {}", style.toStdString());
|
|
|
|
|
+ qApp->setStyle(style);
|
|
|
|
|
+#else
|
|
|
|
|
+ if (CheckDarkMode()) {
|
|
|
|
|
+ // Set Dark palette on non Windows platforms (that may not have a dark palette)
|
|
|
|
|
+ LOG_INFO(Frontend, "Using custom dark palette");
|
|
|
|
|
+ themePalette.setColor(QPalette::Window, QColor(53, 53, 53));
|
|
|
|
|
+ themePalette.setColor(QPalette::WindowText, Qt::white);
|
|
|
|
|
+ themePalette.setColor(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127));
|
|
|
|
|
+ themePalette.setColor(QPalette::Base, QColor(42, 42, 42));
|
|
|
|
|
+ themePalette.setColor(QPalette::AlternateBase, QColor(66, 66, 66));
|
|
|
|
|
+ themePalette.setColor(QPalette::ToolTipBase, Qt::white);
|
|
|
|
|
+ themePalette.setColor(QPalette::ToolTipText, QColor(53, 53, 53));
|
|
|
|
|
+ themePalette.setColor(QPalette::Text, Qt::white);
|
|
|
|
|
+ themePalette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127));
|
|
|
|
|
+ themePalette.setColor(QPalette::Dark, QColor(35, 35, 35));
|
|
|
|
|
+ themePalette.setColor(QPalette::Shadow, QColor(20, 20, 20));
|
|
|
|
|
+ themePalette.setColor(QPalette::Button, QColor(53, 53, 53));
|
|
|
|
|
+ themePalette.setColor(QPalette::ButtonText, Qt::white);
|
|
|
|
|
+ themePalette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127));
|
|
|
|
|
+ themePalette.setColor(QPalette::BrightText, Qt::red);
|
|
|
|
|
+ themePalette.setColor(QPalette::Link, QColor(42, 130, 218));
|
|
|
|
|
+ themePalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
|
|
|
|
|
+ themePalette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80));
|
|
|
|
|
+ themePalette.setColor(QPalette::HighlightedText, Qt::white);
|
|
|
|
|
+ themePalette.setColor(QPalette::Disabled, QPalette::HighlightedText, QColor(127, 127, 127));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ LOG_INFO(Frontend, "Using standard palette");
|
|
|
|
|
+ // Reset light palette on non Windows platforms
|
|
|
|
|
+ themePalette = this->style()->standardPalette();
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
- if (current_theme != default_theme) {
|
|
|
|
|
- QString theme_uri{current_theme + QStringLiteral("style.qss")};
|
|
|
|
|
- if (tryLoadStylesheet(theme_uri)) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // Reading new theme failed, loading default stylesheet
|
|
|
|
|
- LOG_ERROR(Frontend, "Unable to open style \"{}\", fallback to the default theme",
|
|
|
|
|
- current_theme.toStdString());
|
|
|
|
|
-
|
|
|
|
|
- current_theme = default_theme;
|
|
|
|
|
- theme_uri = QStringLiteral(":%1/style.qss").arg(default_theme);
|
|
|
|
|
- if (tryLoadStylesheet(theme_uri)) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ qApp->setPalette(themePalette);
|
|
|
|
|
+ AdjustLinkColor();
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- // Reading default failed, loading empty stylesheet
|
|
|
|
|
- LOG_ERROR(Frontend, "Unable to set style \"{}\", stylesheet file not found",
|
|
|
|
|
- current_theme.toStdString());
|
|
|
|
|
|
|
+void GMainWindow::SetCustomStylesheet() {
|
|
|
|
|
+ setStyleSheet(QStringLiteral("QStatusBar::item { border: none; }"));
|
|
|
|
|
|
|
|
- qApp->setStyleSheet({});
|
|
|
|
|
- setStyleSheet({});
|
|
|
|
|
|
|
+ // Set "dark" qss property value, that may be used in stylesheets
|
|
|
|
|
+ bool is_dark_mode = CheckDarkMode();
|
|
|
|
|
+ if (renderer_status_button) {
|
|
|
|
|
+ renderer_status_button->setProperty("dark", is_dark_mode);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (gpu_accuracy_button) {
|
|
|
|
|
+ gpu_accuracy_button->setProperty("dark", is_dark_mode);
|
|
|
|
|
+ }
|
|
|
|
|
+#ifdef _WIN32
|
|
|
|
|
+ // Windows dark mode uses "fusion" style. Make it look like more "windowsvista" light style
|
|
|
|
|
+ if (is_dark_mode) {
|
|
|
|
|
+ /* the groove expands to the size of the slider by default. by giving it a height, it has a
|
|
|
|
|
+ fixed size */
|
|
|
|
|
+ /* handle is placed by default on the contents rect of the groove. Negative margin expands
|
|
|
|
|
+ it outside the groove */
|
|
|
|
|
+ setStyleSheet(QStringLiteral("QSlider:horizontal{ height:30px; }\
|
|
|
|
|
+ QSlider::sub-page:horizontal { background-color: palette(highlight); }\
|
|
|
|
|
+ QSlider::add-page:horizontal { background-color: palette(midlight);}\
|
|
|
|
|
+ QSlider::groove:horizontal { border-width: 1px; margin: 1px 0; height: 2px;}\
|
|
|
|
|
+ QSlider::handle:horizontal { border-width: 1px; border-style: solid; border-color: palette(dark);\
|
|
|
|
|
+ width: 10px; margin: -10px 0px; }\
|
|
|
|
|
+ QSlider::handle { background-color: palette(button); }\
|
|
|
|
|
+ QSlider::handle:hover { background-color: palette(highlight); }"));
|
|
|
}
|
|
}
|
|
|
|
|
+#endif
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-bool GMainWindow::tryLoadStylesheet(const QString& theme_path) {
|
|
|
|
|
- QFile theme_file(theme_path);
|
|
|
|
|
- if (theme_file.open(QFile::ReadOnly | QFile::Text)) {
|
|
|
|
|
- LOG_INFO(Frontend, "Loading style in: {}", theme_path.toStdString());
|
|
|
|
|
- QTextStream ts(&theme_file);
|
|
|
|
|
- qApp->setStyleSheet(ts.readAll());
|
|
|
|
|
- setStyleSheet(ts.readAll());
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
- // Opening the file failed
|
|
|
|
|
|
|
+#ifdef __unix__
|
|
|
|
|
+bool GMainWindow::ListenColorSchemeChange() {
|
|
|
|
|
+ auto bus = QDBusConnection::sessionBus();
|
|
|
|
|
+ if (bus.isConnected()) {
|
|
|
|
|
+ const QString dbus_service = QStringLiteral("org.freedesktop.portal.Desktop");
|
|
|
|
|
+ const QString dbus_path = QStringLiteral("/org/freedesktop/portal/desktop");
|
|
|
|
|
+ const QString dbus_interface = QStringLiteral("org.freedesktop.portal.Settings");
|
|
|
|
|
+ const QString dbus_method = QStringLiteral("SettingChanged");
|
|
|
|
|
+ QStringList dbus_arguments;
|
|
|
|
|
+ dbus_arguments << QStringLiteral("org.freedesktop.appearance")
|
|
|
|
|
+ << QStringLiteral("color-scheme");
|
|
|
|
|
+ const QString dbus_signature = QStringLiteral("ssv");
|
|
|
|
|
+
|
|
|
|
|
+ LOG_INFO(Frontend, "Connected to DBus, listening for OS theme changes");
|
|
|
|
|
+ return bus.connect(dbus_service, dbus_path, dbus_interface, dbus_method, dbus_arguments,
|
|
|
|
|
+ dbus_signature, this, SLOT(UpdateUITheme()));
|
|
|
|
|
+ }
|
|
|
|
|
+ LOG_WARNING(Frontend, "Unable to connect to DBus to listen for OS theme changes");
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+bool GMainWindow::CheckDarkMode() {
|
|
|
|
|
+ const QPalette current_palette(qApp->palette());
|
|
|
|
|
+#ifdef __unix__
|
|
|
|
|
+ QProcess process;
|
|
|
|
|
+ QStringList gdbus_arguments;
|
|
|
|
|
+
|
|
|
|
|
+ // Using the freedesktop specifications for checking dark mode
|
|
|
|
|
+ LOG_INFO(Frontend, "Retrieving theme from freedesktop color-scheme...");
|
|
|
|
|
+ gdbus_arguments << QStringLiteral("--dest=org.freedesktop.portal.Desktop")
|
|
|
|
|
+ << QStringLiteral("--object-path /org/freedesktop/portal/desktop")
|
|
|
|
|
+ << QStringLiteral("--method org.freedesktop.portal.Settings.Read "
|
|
|
|
|
+ "org.freedesktop.appearance color-scheme");
|
|
|
|
|
+ process.start(QStringLiteral("gdbus call --session"), gdbus_arguments);
|
|
|
|
|
+ process.waitForFinished(1000);
|
|
|
|
|
+ QByteArray dbus_output = process.readAllStandardOutput();
|
|
|
|
|
+
|
|
|
|
|
+ if (!dbus_output.isEmpty()) {
|
|
|
|
|
+ const int systemColorSchema = QString::fromUtf8(dbus_output).trimmed().right(1).toInt();
|
|
|
|
|
+ return systemColorSchema == 1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Try alternative for Gnome if the previous one failed
|
|
|
|
|
+ QStringList gsettings_arguments;
|
|
|
|
|
+ gsettings_arguments << QStringLiteral("get")
|
|
|
|
|
+ << QStringLiteral("org.gnome.desktop.interface")
|
|
|
|
|
+ << QStringLiteral("color-scheme");
|
|
|
|
|
+
|
|
|
|
|
+ LOG_DEBUG(Frontend, "failed, retrieving theme from gsettings color-scheme...");
|
|
|
|
|
+ process.start(QStringLiteral("gsettings"), gsettings_arguments);
|
|
|
|
|
+ process.waitForFinished(1000);
|
|
|
|
|
+ QByteArray gsettings_output = process.readAllStandardOutput();
|
|
|
|
|
+
|
|
|
|
|
+ // Try older gtk-theme method if the previous one failed
|
|
|
|
|
+ if (gsettings_output.isEmpty()) {
|
|
|
|
|
+ LOG_INFO(Frontend, "failed, retrieving theme from gtk-theme...");
|
|
|
|
|
+ gsettings_arguments.takeLast();
|
|
|
|
|
+ gsettings_arguments << QStringLiteral("gtk-theme");
|
|
|
|
|
+
|
|
|
|
|
+ process.start(QStringLiteral("gsettings"), gsettings_arguments);
|
|
|
|
|
+ process.waitForFinished(1000);
|
|
|
|
|
+ gsettings_output = process.readAllStandardOutput();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Interpret gsettings value if it succeeded
|
|
|
|
|
+ if (!gsettings_output.isEmpty()) {
|
|
|
|
|
+ QString systeme_theme = QString::fromUtf8(gsettings_output);
|
|
|
|
|
+ LOG_DEBUG(Frontend, "Gsettings output: {}", systeme_theme.toStdString());
|
|
|
|
|
+ return systeme_theme.contains(QStringLiteral("dark"), Qt::CaseInsensitive);
|
|
|
|
|
+ }
|
|
|
|
|
+ LOG_DEBUG(Frontend, "failed, retrieving theme from palette");
|
|
|
|
|
+#endif
|
|
|
|
|
+ // Use default method based on palette swap by OS.
|
|
|
|
|
+ // It is the only method on Windows with Qt 5.
|
|
|
|
|
+ // Windows needs QT_QPA_PLATFORM env variable set to windows:darkmode=2 to force palette change
|
|
|
|
|
+ return (current_palette.color(QPalette::WindowText).lightness() >
|
|
|
|
|
+ current_palette.color(QPalette::Window).lightness());
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void GMainWindow::changeEvent(QEvent* event) {
|
|
|
|
|
+ // PaletteChange event appears to only reach so far into the GUI, explicitly asking to
|
|
|
|
|
+ // UpdateUITheme is a decent work around
|
|
|
|
|
+ if (event->type() == QEvent::PaletteChange ||
|
|
|
|
|
+ event->type() == QEvent::ApplicationPaletteChange) {
|
|
|
|
|
+ LOG_INFO(Frontend,
|
|
|
|
|
+ "Window color palette changed by event: {} (QEvent::PaletteChange is: {})",
|
|
|
|
|
+ event->type(), QEvent::PaletteChange);
|
|
|
|
|
+ const QPalette test_palette(qApp->palette());
|
|
|
|
|
+ // Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too
|
|
|
|
|
+ const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
|
|
|
|
|
+
|
|
|
|
|
+ if (last_window_color != window_color) {
|
|
|
|
|
+ last_window_color = window_color;
|
|
|
|
|
+
|
|
|
|
|
+ UpdateUITheme();
|
|
|
|
|
+ }
|
|
|
|
|
+ } else QWidget::changeEvent(event);
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
void GMainWindow::LoadTranslation() {
|
|
void GMainWindow::LoadTranslation() {
|
|
|
bool loaded;
|
|
bool loaded;
|
|
@@ -4935,26 +5151,6 @@ void GMainWindow::SetGamemodeEnabled(bool state) {
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
-void GMainWindow::changeEvent(QEvent* event) {
|
|
|
|
|
-#ifdef __unix__
|
|
|
|
|
- // PaletteChange event appears to only reach so far into the GUI, explicitly asking to
|
|
|
|
|
- // UpdateUITheme is a decent work around
|
|
|
|
|
- if (event->type() == QEvent::PaletteChange) {
|
|
|
|
|
- const QPalette test_palette(qApp->palette());
|
|
|
|
|
- const QString& current_theme = UISettings::values.theme;
|
|
|
|
|
- // Keeping eye on QPalette::Window to avoid looping. QPalette::Text might be useful too
|
|
|
|
|
- static QColor last_window_color;
|
|
|
|
|
- const QColor window_color = test_palette.color(QPalette::Active, QPalette::Window);
|
|
|
|
|
- if (last_window_color != window_color && (current_theme == QStringLiteral("default") ||
|
|
|
|
|
- current_theme == QStringLiteral("colorful"))) {
|
|
|
|
|
- UpdateUITheme();
|
|
|
|
|
- }
|
|
|
|
|
- last_window_color = window_color;
|
|
|
|
|
- }
|
|
|
|
|
-#endif // __unix__
|
|
|
|
|
- QWidget::changeEvent(event);
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
Service::AM::FrontendAppletParameters GMainWindow::ApplicationAppletParameters() {
|
|
Service::AM::FrontendAppletParameters GMainWindow::ApplicationAppletParameters() {
|
|
|
return Service::AM::FrontendAppletParameters{
|
|
return Service::AM::FrontendAppletParameters{
|
|
|
.applet_id = Service::AM::AppletId::Application,
|
|
.applet_id = Service::AM::AppletId::Application,
|