Skip to content

Commit

Permalink
feat: add system theme on Qt 6.5 and up (Chatterino#5118)
Browse files Browse the repository at this point in the history
* feat: add system theme on Qt 6.5

* chroe: add changelog entry

* refactor: add separate settings

* fix: qt 5

* Update changelog entry

---------

Co-authored-by: Rasmus Karlsson <[email protected]>
  • Loading branch information
Nerixyz and pajlada authored Jan 27, 2024
1 parent 7d7f1b3 commit c32ee8e
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- Minor: Normalized the input padding between light & dark themes. (#5095)
- Minor: Add `--activate <channel>` (or `-a`) command line option to activate or add a Twitch channel. (#5111)
- Minor: Chatters from recent-messages are now added to autocompletion. (#5116)
- Minor: Added a _System_ theme that updates according to the system's color scheme (requires Qt 6.5). (#5118)
- Minor: Added support for the `{input.text}` placeholder in the **Split** -> **Run a command** hotkey. (#5130)
- Bugfix: Fixed an issue where certain emojis did not send to Twitch chat correctly. (#4840)
- Bugfix: Fixed capitalized channel names in log inclusion list not being logged. (#4848)
Expand Down
47 changes: 46 additions & 1 deletion src/singletons/Theme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,17 @@
#include "common/QLogging.hpp"
#include "singletons/Paths.hpp"
#include "singletons/Resources.hpp"
#include "singletons/WindowManager.hpp"

#include <QColor>
#include <QDir>
#include <QElapsedTimer>
#include <QFile>
#include <QJsonDocument>
#include <QSet>
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
# include <QStyleHints>
#endif

#include <cmath>

Expand Down Expand Up @@ -219,6 +223,11 @@ bool Theme::isLightTheme() const
return this->isLight_;
}

bool Theme::isSystemTheme() const
{
return this->themeName == u"System"_s;
}

void Theme::initialize(Settings &settings, const Paths &paths)
{
this->themeName.connect(
Expand All @@ -227,15 +236,51 @@ void Theme::initialize(Settings &settings, const Paths &paths)
this->update();
},
false);
auto updateIfSystem = [this](const auto &) {
if (this->isSystemTheme())
{
this->update();
}
};
this->darkSystemThemeName.connect(updateIfSystem, false);
this->lightSystemThemeName.connect(updateIfSystem, false);

this->loadAvailableThemes(paths);

#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
QObject::connect(qApp->styleHints(), &QStyleHints::colorSchemeChanged,
&this->lifetime_, [this] {
if (this->isSystemTheme())
{
this->update();
getIApp()->getWindows()->forceLayoutChannelViews();
}
});
#endif

this->update();
}

void Theme::update()
{
auto oTheme = this->findThemeByKey(this->themeName);
auto currentTheme = [&]() -> QString {
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
if (this->isSystemTheme())
{
switch (qApp->styleHints()->colorScheme())
{
case Qt::ColorScheme::Light:
return this->lightSystemThemeName;
case Qt::ColorScheme::Unknown:
case Qt::ColorScheme::Dark:
return this->darkSystemThemeName;
}
}
#endif
return this->themeName;
};

auto oTheme = this->findThemeByKey(currentTheme());

constexpr const double nsToMs = 1.0 / 1000000.0;
QElapsedTimer timer;
Expand Down
6 changes: 6 additions & 0 deletions src/singletons/Theme.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class Theme final : public Singleton
void initialize(Settings &settings, const Paths &paths) final;

bool isLightTheme() const;
bool isSystemTheme() const;

struct TabColors {
QColor text;
Expand Down Expand Up @@ -153,6 +154,9 @@ class Theme final : public Singleton
pajlada::Signals::NoArgSignal updated;

QStringSetting themeName{"/appearance/theme/name", "Dark"};
QStringSetting lightSystemThemeName{"/appearance/theme/lightSystem",
"Light"};
QStringSetting darkSystemThemeName{"/appearance/theme/darkSystem", "Dark"};

private:
bool isLight_ = false;
Expand All @@ -164,6 +168,8 @@ class Theme final : public Singleton
// This will only be populated when auto-reloading themes
QJsonObject currentThemeJson_;

QObject lifetime_;

/**
* Figure out which themes are available in the Themes directory
*
Expand Down
53 changes: 43 additions & 10 deletions src/widgets/settingspages/GeneralPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,49 @@ void GeneralPage::initLayout(GeneralPageView &layout)

layout.addTitle("Interface");

layout.addDropdown<QString>(
"Theme", getIApp()->getThemes()->availableThemes(),
getIApp()->getThemes()->themeName,
[](const auto *combo, const auto &themeKey) {
return combo->findData(themeKey, Qt::UserRole);
},
[](const auto &args) {
return args.combobox->itemData(args.index, Qt::UserRole).toString();
},
{}, Theme::fallbackTheme.name);
{
auto *themes = getIApp()->getThemes();
auto available = themes->availableThemes();
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
available.emplace_back("System", "System");
#endif

auto addThemeDropdown = [&](auto name, auto &setting,
const auto &options,
const QString &tooltip = {}) {
return layout.addDropdown<QString>(
name, options, setting,
[](const auto *combo, const auto &themeKey) {
return combo->findData(themeKey, Qt::UserRole);
},
[](const auto &args) {
return args.combobox->itemData(args.index, Qt::UserRole)
.toString();
},
tooltip, Theme::fallbackTheme.name);
};

addThemeDropdown("Theme", themes->themeName, available);

#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
auto *darkDropdown = addThemeDropdown(
"Dark system theme", themes->darkSystemThemeName,
themes->availableThemes(),
"This theme is selected if your system is in a dark theme and you "
"enabled the adaptive 'System' theme.");
auto *lightDropdown = addThemeDropdown(
"Light system theme", themes->lightSystemThemeName,
themes->availableThemes(),
"This theme is selected if your system is in a light theme and you "
"enabled the adaptive 'System' theme.");

auto isSystem = [](const auto &s) {
return s == "System";
};
layout.enableIf(darkDropdown, themes->themeName, isSystem);
layout.enableIf(lightDropdown, themes->themeName, isSystem);
#endif
}

layout.addDropdown<QString>(
"Font", {"Segoe UI", "Arial", "Choose..."},
Expand Down
9 changes: 9 additions & 0 deletions src/widgets/settingspages/GeneralPageView.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,15 @@ class GeneralPageView : public QWidget
return combo;
}

void enableIf(QComboBox *widget, auto &setting, auto cb)
{
auto updateVisibility = [cb = std::move(cb), &setting, widget]() {
auto enabled = cb(setting.getValue());
widget->setEnabled(enabled);
};
setting.connect(updateVisibility, this->managedConnections_);
}

DescriptionLabel *addDescription(const QString &text);

void addSeperator();
Expand Down

0 comments on commit c32ee8e

Please sign in to comment.