Refactor StreamerMode/Theme setting widgets (#6317)
This commit is contained in:
@@ -70,6 +70,7 @@
|
||||
- Dev: Merged top/bottom and left/right notebook layouts. (#6215)
|
||||
- Dev: Refactored `Button` and friends. (#6102, #6255, #6266, #6302, #6268)
|
||||
- Dev: Made Settings & Account button on Linux/macOS SVGs. (#6267)
|
||||
- Dev: Some more setting widget refactors. (#6317)
|
||||
- Dev: Emoji style / set is now stored lowercase (and matched case-insensitively). Changing emoji style from this point on and then running an old version might mean you will use the Twitter emoji style by default. (#6300)
|
||||
- Dev: Refactored `OnceFlag`. (#6237, #6316)
|
||||
- Dev: Bumped clang-format requirement to 19. (#6236)
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
namespace chatterino {
|
||||
|
||||
enum StreamerModeSetting : std::uint8_t {
|
||||
Disabled,
|
||||
Enabled,
|
||||
DetectStreamingSoftware,
|
||||
};
|
||||
|
||||
constexpr std::optional<std::string_view> qmagicenumDisplayName(
|
||||
StreamerModeSetting value) noexcept
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case Disabled:
|
||||
return "Disabled";
|
||||
|
||||
case Enabled:
|
||||
return "Enabled";
|
||||
|
||||
case DetectStreamingSoftware:
|
||||
return "Automatic (Detect streaming software)";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "common/LastMessageLineStyle.hpp"
|
||||
#include "common/Modes.hpp"
|
||||
#include "common/SignalVector.hpp"
|
||||
#include "common/StreamerModeSetting.hpp"
|
||||
#include "common/ThumbnailPreviewMode.hpp"
|
||||
#include "common/TimeoutStackStyle.hpp"
|
||||
#include "controllers/filters/FilterRecord.hpp"
|
||||
@@ -84,12 +85,6 @@ enum class StreamLinkPreferredQuality : std::uint8_t {
|
||||
AudioOnly,
|
||||
};
|
||||
|
||||
enum StreamerModeSetting {
|
||||
Disabled = 0,
|
||||
Enabled = 1,
|
||||
DetectStreamingSoftware = 2,
|
||||
};
|
||||
|
||||
enum class TabStyle : std::uint8_t {
|
||||
Normal,
|
||||
Compact,
|
||||
@@ -402,7 +397,9 @@ public:
|
||||
// - "Always hide"
|
||||
// - "Don't hide"
|
||||
EnumSetting<StreamerModeSetting> enableStreamerMode = {
|
||||
"/streamerMode/enabled", StreamerModeSetting::DetectStreamingSoftware};
|
||||
"/streamerMode/enabled",
|
||||
StreamerModeSetting::DetectStreamingSoftware,
|
||||
};
|
||||
BoolSetting streamerModeHideUsercardAvatars = {
|
||||
"/streamerMode/hideUsercardAvatars", true};
|
||||
BoolSetting streamerModeHideLinkThumbnails = {
|
||||
|
||||
@@ -131,40 +131,25 @@ void GeneralPage::initLayout(GeneralPageView &layout)
|
||||
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);
|
||||
SettingWidget::dropdown("Theme", themes->themeName, available)
|
||||
->addTo(layout);
|
||||
|
||||
#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.");
|
||||
SettingWidget::dropdown("Dark system theme",
|
||||
themes->darkSystemThemeName,
|
||||
themes->availableThemes())
|
||||
->setTooltip("This theme is selected if your system is in a dark "
|
||||
"theme and you enabled the adaptive 'System' theme.")
|
||||
->conditionallyEnabledBy(themes->themeName, "System")
|
||||
->addTo(layout);
|
||||
|
||||
auto isSystem = [](const auto &s) {
|
||||
return s == "System";
|
||||
};
|
||||
layout.enableIf(darkDropdown, themes->themeName, isSystem);
|
||||
layout.enableIf(lightDropdown, themes->themeName, isSystem);
|
||||
SettingWidget::dropdown("Light system theme",
|
||||
themes->lightSystemThemeName,
|
||||
themes->availableThemes())
|
||||
->setTooltip("This theme is selected if your system is in a light "
|
||||
"theme and you enabled the adaptive 'System' theme.")
|
||||
->conditionallyEnabledBy(themes->themeName, "System")
|
||||
->addTo(layout);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -705,19 +690,8 @@ void GeneralPage::initLayout(GeneralPageView &layout)
|
||||
"streaming software is running.\nSelect which things you want to "
|
||||
"change while streaming");
|
||||
|
||||
ComboBox *dankDropdown =
|
||||
layout.addDropdown<std::underlying_type_t<StreamerModeSetting>>(
|
||||
"Enable Streamer Mode",
|
||||
{"Disabled", "Enabled", "Automatic (Detect streaming software)"},
|
||||
s.enableStreamerMode,
|
||||
[](int value) {
|
||||
return value;
|
||||
},
|
||||
[](DropdownArgs args) {
|
||||
return static_cast<StreamerModeSetting>(args.index);
|
||||
},
|
||||
false);
|
||||
dankDropdown->setMinimumWidth(dankDropdown->minimumSizeHint().width() + 30);
|
||||
SettingWidget::dropdown("Enable Streamer Mode", s.enableStreamerMode)
|
||||
->addTo(layout);
|
||||
|
||||
SettingWidget::checkbox("Hide usercard avatars",
|
||||
s.streamerModeHideUsercardAvatars)
|
||||
|
||||
@@ -183,34 +183,6 @@ ComboBox *GeneralPageView::addDropdown(const QString &text,
|
||||
return combo;
|
||||
}
|
||||
|
||||
ComboBox *GeneralPageView::addDropdown(
|
||||
const QString &text, const QStringList &items,
|
||||
pajlada::Settings::Setting<QString> &setting, bool editable,
|
||||
QString toolTipText)
|
||||
{
|
||||
auto *combo = this->addDropdown(text, items, toolTipText);
|
||||
|
||||
if (editable)
|
||||
{
|
||||
combo->setEditable(true);
|
||||
}
|
||||
|
||||
// update when setting changes
|
||||
setting.connect(
|
||||
[combo](const QString &value, auto) {
|
||||
combo->setCurrentText(value);
|
||||
},
|
||||
this->managedConnections_);
|
||||
|
||||
QObject::connect(combo, &QComboBox::currentTextChanged,
|
||||
[&setting](const QString &newValue) {
|
||||
setting = newValue;
|
||||
getApp()->getWindows()->forceLayoutChannelViews();
|
||||
});
|
||||
|
||||
return combo;
|
||||
}
|
||||
|
||||
void GeneralPageView::addNavigationSpacing()
|
||||
{
|
||||
assert(this->navigationLayout_ != nullptr &&
|
||||
|
||||
@@ -134,9 +134,6 @@ public:
|
||||
|
||||
ComboBox *addDropdown(const QString &text, const QStringList &items,
|
||||
QString toolTipText = {});
|
||||
ComboBox *addDropdown(const QString &text, const QStringList &items,
|
||||
pajlada::Settings::Setting<QString> &setting,
|
||||
bool editable = false, QString toolTipText = {});
|
||||
void addNavigationSpacing();
|
||||
|
||||
template <typename OnClick>
|
||||
@@ -240,67 +237,6 @@ public:
|
||||
return combo;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ComboBox *addDropdown(
|
||||
const QString &text,
|
||||
const std::vector<std::pair<QString, QVariant>> &items,
|
||||
pajlada::Settings::Setting<T> &setting,
|
||||
std::function<boost::variant<int, QString>(ComboBox *, T)> getValue,
|
||||
std::function<T(DropdownArgs)> setValue, QString toolTipText = {},
|
||||
const QString &defaultValueText = {})
|
||||
{
|
||||
auto *combo = this->addDropdown(text, {}, std::move(toolTipText));
|
||||
|
||||
for (const auto &[itemText, userData] : items)
|
||||
{
|
||||
combo->addItem(itemText, userData);
|
||||
}
|
||||
|
||||
if (!defaultValueText.isEmpty())
|
||||
{
|
||||
combo->setCurrentText(defaultValueText);
|
||||
}
|
||||
|
||||
setting.connect(
|
||||
[getValue = std::move(getValue), combo](const T &value, auto) {
|
||||
auto var = getValue(combo, value);
|
||||
if (var.which() == 0)
|
||||
{
|
||||
const auto index = boost::get<int>(var);
|
||||
if (index >= 0)
|
||||
{
|
||||
combo->setCurrentIndex(index);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
combo->setCurrentText(boost::get<QString>(var));
|
||||
combo->setEditText(boost::get<QString>(var));
|
||||
}
|
||||
},
|
||||
this->managedConnections_);
|
||||
|
||||
QObject::connect(
|
||||
combo, QOverload<const int>::of(&QComboBox::currentIndexChanged),
|
||||
[combo, &setting,
|
||||
setValue = std::move(setValue)](const int newIndex) {
|
||||
setting = setValue(DropdownArgs{combo->itemText(newIndex),
|
||||
combo->currentIndex(), combo});
|
||||
getApp()->getWindows()->forceLayoutChannelViews();
|
||||
});
|
||||
|
||||
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 addSeparator();
|
||||
|
||||
@@ -181,7 +181,7 @@ SettingWidget *SettingWidget::dropdown(const QString &label,
|
||||
}
|
||||
|
||||
// TODO: this can probably use some other size hint/size strategy
|
||||
combo->setMinimumWidth(combo->minimumSizeHint().width());
|
||||
combo->setMinimumWidth(combo->minimumSizeHint().width() + 30);
|
||||
|
||||
widget->actionWidget = combo;
|
||||
widget->label = lbl;
|
||||
@@ -254,7 +254,7 @@ SettingWidget *SettingWidget::dropdown(const QString &label,
|
||||
}
|
||||
|
||||
// TODO: this can probably use some other size hint/size strategy
|
||||
combo->setMinimumWidth(combo->minimumSizeHint().width());
|
||||
combo->setMinimumWidth(combo->minimumSizeHint().width() + 30);
|
||||
|
||||
widget->actionWidget = combo;
|
||||
widget->label = lbl;
|
||||
@@ -313,6 +313,72 @@ template SettingWidget *SettingWidget::dropdown<LastMessageLineStyle>(
|
||||
const QString &label, EnumSetting<LastMessageLineStyle> &setting);
|
||||
template SettingWidget *SettingWidget::dropdown<ThumbnailPreviewMode>(
|
||||
const QString &label, EnumSetting<ThumbnailPreviewMode> &setting);
|
||||
template SettingWidget *SettingWidget::dropdown<StreamerModeSetting>(
|
||||
const QString &label, EnumSetting<StreamerModeSetting> &setting);
|
||||
|
||||
SettingWidget *SettingWidget::dropdown(
|
||||
const QString &label, QStringSetting &setting,
|
||||
const std::vector<std::pair<QString, QVariant>> &items)
|
||||
{
|
||||
auto *widget = new SettingWidget(label);
|
||||
|
||||
auto *lbl = new QLabel(label % ":");
|
||||
auto *combo = new ComboBox;
|
||||
combo->setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
for (const auto &[itemText, itemData] : items)
|
||||
{
|
||||
combo->addItem(itemText, itemData);
|
||||
}
|
||||
|
||||
// TODO: this can probably use some other size hint/size strategy
|
||||
combo->setMinimumWidth(combo->minimumSizeHint().width() + 30);
|
||||
|
||||
widget->actionWidget = combo;
|
||||
widget->label = lbl;
|
||||
|
||||
widget->hLayout->addWidget(lbl);
|
||||
widget->hLayout->addStretch(1);
|
||||
widget->hLayout->addWidget(combo);
|
||||
|
||||
setting.connect(
|
||||
[combo, label](const auto &value) {
|
||||
std::optional<int> foundRow;
|
||||
|
||||
for (auto row = 0; row < combo->model()->rowCount(); ++row)
|
||||
{
|
||||
auto index = combo->model()->index(row, 0);
|
||||
auto rowEnumValue = index.data(Qt::UserRole);
|
||||
if (rowEnumValue == value)
|
||||
{
|
||||
foundRow = row;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundRow)
|
||||
{
|
||||
combo->setCurrentIndex(*foundRow);
|
||||
}
|
||||
else
|
||||
{
|
||||
qCWarning(chatterinoWidget)
|
||||
<< "Did not find a correct combo box row for" << label
|
||||
<< " with value" << value;
|
||||
}
|
||||
},
|
||||
widget->managedConnections);
|
||||
|
||||
QObject::connect(combo, &QComboBox::currentTextChanged,
|
||||
[label, combo, &setting](const auto &newText) {
|
||||
bool ok = true;
|
||||
auto stringValue = combo->currentData().toString();
|
||||
|
||||
setting.setValue(stringValue);
|
||||
});
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
SettingWidget *SettingWidget::colorButton(const QString &label,
|
||||
QStringSetting &setting)
|
||||
@@ -498,26 +564,39 @@ SettingWidget *SettingWidget::conditionallyEnabledBy(BoolSetting &setting)
|
||||
return this;
|
||||
}
|
||||
|
||||
SettingWidget *SettingWidget::conditionallyEnabledBy(
|
||||
QStringSetting &setting, const QString &expectedValue)
|
||||
{
|
||||
setting.connect(
|
||||
[this, expectedValue](const auto &value, const auto &) {
|
||||
this->actionWidget->setEnabled(value == expectedValue);
|
||||
},
|
||||
this->managedConnections);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void SettingWidget::addTo(GeneralPageView &view)
|
||||
{
|
||||
view.pushWidget(this);
|
||||
|
||||
if (this->label != nullptr)
|
||||
{
|
||||
view.registerWidget(this->label, this->keywords, this);
|
||||
}
|
||||
view.registerWidget(this->actionWidget, this->keywords, this);
|
||||
this->registerWidget(view);
|
||||
}
|
||||
|
||||
void SettingWidget::addTo(GeneralPageView &view, QFormLayout *formLayout)
|
||||
{
|
||||
this->registerWidget(view);
|
||||
|
||||
formLayout->addRow(this->label, this->actionWidget);
|
||||
}
|
||||
|
||||
void SettingWidget::registerWidget(GeneralPageView &view)
|
||||
{
|
||||
if (this->label != nullptr)
|
||||
{
|
||||
view.registerWidget(this->label, this->keywords, this);
|
||||
}
|
||||
view.registerWidget(this->actionWidget, this->keywords, this);
|
||||
|
||||
formLayout->addRow(this->label, this->actionWidget);
|
||||
}
|
||||
|
||||
} // namespace chatterino
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
class QFormLayout;
|
||||
|
||||
@@ -66,14 +68,25 @@ public:
|
||||
intInput(const QString &label, IntSetting &setting,
|
||||
IntInputParams params);
|
||||
|
||||
/// Create a dropdown backed by an enum
|
||||
///
|
||||
/// The setting itself expects the enum name (i.e. "Foo")
|
||||
template <typename T>
|
||||
[[nodiscard("Must use created setting widget")]] static SettingWidget *
|
||||
dropdown(const QString &label, EnumStringSetting<T> &setting);
|
||||
|
||||
/// Create a dropdown backed by an enum
|
||||
///
|
||||
/// The setting itself expects the enum value (i.e. 3)
|
||||
template <typename T>
|
||||
[[nodiscard("Must use created setting widget")]] static SettingWidget *
|
||||
dropdown(const QString &label, EnumSetting<T> &setting);
|
||||
|
||||
/// Create a dropdown for a String setting that is not backed by an enum
|
||||
[[nodiscard("Must use created setting widget")]] static SettingWidget *
|
||||
dropdown(const QString &label, QStringSetting &setting,
|
||||
const std::vector<std::pair<QString, QVariant>> &items);
|
||||
|
||||
[[nodiscard("Must use created setting widget")]] static SettingWidget *
|
||||
colorButton(const QString &label, QStringSetting &setting);
|
||||
[[nodiscard("Must use created setting widget")]] static SettingWidget *
|
||||
@@ -96,13 +109,22 @@ public:
|
||||
[[nodiscard("Must use created setting widget")]] SettingWidget *addKeywords(
|
||||
const QStringList &newKeywords);
|
||||
|
||||
/// Conditionally enable the widget if the given bool setting is true
|
||||
[[nodiscard("Must use created setting widget")]] SettingWidget *
|
||||
conditionallyEnabledBy(BoolSetting &setting);
|
||||
|
||||
/// Conditionally enable the widget if the given string setting is equal to expectedValue
|
||||
[[nodiscard("Must use created setting widget")]] SettingWidget *
|
||||
conditionallyEnabledBy(QStringSetting &setting,
|
||||
const QString &expectedValue);
|
||||
|
||||
void addTo(GeneralPageView &view);
|
||||
void addTo(GeneralPageView &view, QFormLayout *formLayout);
|
||||
|
||||
private:
|
||||
/// Registers this widget & its optional label to the given page view
|
||||
void registerWidget(GeneralPageView &view);
|
||||
|
||||
QWidget *label = nullptr;
|
||||
QWidget *actionWidget = nullptr;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user