diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4a20d28e..d3b1e3bd 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -31,6 +31,7 @@ set(SOURCE_FILES common/Credentials.hpp common/Env.cpp common/Env.hpp + common/LastMessageLineStyle.hpp common/LinkParser.cpp common/LinkParser.hpp common/Literals.hpp @@ -38,6 +39,7 @@ set(SOURCE_FILES common/Modes.hpp common/QLogging.cpp common/QLogging.hpp + common/ThumbnailPreviewMode.hpp common/TimeoutStackStyle.hpp common/WindowDescriptors.cpp common/WindowDescriptors.hpp diff --git a/src/common/ChatterinoSetting.hpp b/src/common/ChatterinoSetting.hpp index 84242838..9d72bd03 100644 --- a/src/common/ChatterinoSetting.hpp +++ b/src/common/ChatterinoSetting.hpp @@ -62,6 +62,9 @@ using StringSetting = ChatterinoSetting; using QStringSetting = ChatterinoSetting; using QSizeSetting = ChatterinoSetting; +/// Accepts any enum and saves the enum value as an integer +/// +/// e.g. for enum class {Foo = 2, Bar = 6}, Foo would be saved as 2 and Bar would be saved as 6 template class EnumSetting : public ChatterinoSetting> { diff --git a/src/common/LastMessageLineStyle.hpp b/src/common/LastMessageLineStyle.hpp new file mode 100644 index 00000000..b03beda1 --- /dev/null +++ b/src/common/LastMessageLineStyle.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include + +#include + +namespace chatterino { + +/// The values must always be castable to a Qt::BrushStyle +// NOLINTNEXTLINE(performance-enum-size) +enum class LastMessageLineStyle : std::underlying_type_t { + Solid = Qt::SolidPattern, + Dotted = Qt::VerPattern, +}; + +} // namespace chatterino diff --git a/src/common/ThumbnailPreviewMode.hpp b/src/common/ThumbnailPreviewMode.hpp new file mode 100644 index 00000000..d99f94d7 --- /dev/null +++ b/src/common/ThumbnailPreviewMode.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include + +namespace chatterino { + +enum class ThumbnailPreviewMode : std::uint8_t { + DontShow, + + AlwaysShow, + + ShowOnShift, +}; + +constexpr std::optional qmagicenumDisplayName( + ThumbnailPreviewMode value) noexcept +{ + switch (value) + { + case ThumbnailPreviewMode::DontShow: + return "Don't show"; + case ThumbnailPreviewMode::AlwaysShow: + return "Always show"; + case ThumbnailPreviewMode::ShowOnShift: + return "Hold shift"; + } +} + +} // namespace chatterino diff --git a/src/singletons/Settings.hpp b/src/singletons/Settings.hpp index a12e9731..ff7ef415 100644 --- a/src/singletons/Settings.hpp +++ b/src/singletons/Settings.hpp @@ -2,8 +2,10 @@ #include "common/ChatterinoSetting.hpp" #include "common/enums/MessageOverflow.hpp" +#include "common/LastMessageLineStyle.hpp" #include "common/Modes.hpp" #include "common/SignalVector.hpp" +#include "common/ThumbnailPreviewMode.hpp" #include "common/TimeoutStackStyle.hpp" #include "controllers/filters/FilterRecord.hpp" #include "controllers/highlights/HighlightBadge.hpp" @@ -16,7 +18,6 @@ #include "controllers/sound/ISoundController.hpp" #include "providers/emoji/EmojiStyle.hpp" #include "singletons/Toasts.hpp" -#include "util/QMagicEnumTagged.hpp" #include "util/RapidJsonSerializeQString.hpp" // IWYU pragma: keep #include "widgets/NotebookEnums.hpp" @@ -24,6 +25,9 @@ #include #include +#include +#include + using TimeoutButton = std::pair; namespace chatterino { @@ -52,14 +56,6 @@ enum UsernameDisplayMode : int { UsernameAndLocalizedName = 3, // Username (Localized name) }; -enum ThumbnailPreviewMode : int { - DontShow = 0, - - AlwaysShow = 1, - - ShowOnShift = 2, -}; - enum UsernameRightClickBehavior : int { Reply = 0, Mention = 1, @@ -106,7 +102,7 @@ enum class EmoteTooltipScale : std::uint8_t { Huge, }; -constexpr qmagicenum::customize_t qmagicenumDisplayName( +constexpr std::optional qmagicenumDisplayName( EmoteTooltipScale value) noexcept { switch (value) @@ -163,8 +159,10 @@ public: "h:mm"}; BoolSetting showLastMessageIndicator = { "/appearance/messages/showLastMessageIndicator", false}; - EnumSetting lastMessagePattern = { - "/appearance/messages/lastMessagePattern", Qt::SolidPattern}; + EnumSetting lastMessagePattern = { + "/appearance/messages/lastMessagePattern", + LastMessageLineStyle::Solid, + }; QStringSetting lastMessageColor = {"/appearance/messages/lastMessageColor", "#7f2026"}; BoolSetting showEmptyInput = {"/appearance/showEmptyInputBox", true}; diff --git a/src/widgets/helper/ChannelView.cpp b/src/widgets/helper/ChannelView.cpp index a27adad8..21d5c34a 100644 --- a/src/widgets/helper/ChannelView.cpp +++ b/src/widgets/helper/ChannelView.cpp @@ -2046,7 +2046,7 @@ void ChannelView::mouseMoveEvent(QMouseEvent *event) if (badgeElement || emoteElement || layeredEmoteElement) { auto showThumbnailSetting = - getSettings()->emotesTooltipPreview.getValue(); + getSettings()->emotesTooltipPreview.getEnum(); bool showThumbnail = showThumbnailSetting == ThumbnailPreviewMode::AlwaysShow || diff --git a/src/widgets/settingspages/GeneralPage.cpp b/src/widgets/settingspages/GeneralPage.cpp index a177b668..f73e9737 100644 --- a/src/widgets/settingspages/GeneralPage.cpp +++ b/src/widgets/settingspages/GeneralPage.cpp @@ -3,6 +3,7 @@ #include "Application.hpp" #include "common/Literals.hpp" #include "common/QLogging.hpp" +#include "common/ThumbnailPreviewMode.hpp" #include "common/Version.hpp" #include "controllers/hotkeys/HotkeyCategory.hpp" #include "controllers/hotkeys/HotkeyController.hpp" @@ -552,29 +553,8 @@ void GeneralPage::initLayout(GeneralPageView &layout) s.showLastMessageIndicator, false, "Adds an underline below the most recent message " "sent before you tabbed out of Chatterino."); - layout.addDropdown>( - "Line style", {"Dotted", "Solid"}, s.lastMessagePattern, - [](int value) { - switch (value) - { - case Qt::VerPattern: - return 0; - case Qt::SolidPattern: - default: - return 1; - } - }, - [](DropdownArgs args) { - switch (args.index) - { - case 0: - return Qt::VerPattern; - case 1: - default: - return Qt::SolidPattern; - } - }, - false); + + SettingWidget::dropdown("Line style", s.lastMessagePattern)->addTo(layout); SettingWidget::colorButton("Line color", s.lastMessageColor)->addTo(layout); @@ -634,30 +614,11 @@ void GeneralPage::initLayout(GeneralPageView &layout) }); }, false); - layout.addDropdown>( - "Show emote & badge thumbnail on hover", - { - "Don't show", - "Always show", - "Hold shift", - }, - s.emotesTooltipPreview, - [](auto val) { - switch (val) - { - case ThumbnailPreviewMode::DontShow: - return "Don't show"; - case ThumbnailPreviewMode::AlwaysShow: - return "Always show"; - case ThumbnailPreviewMode::ShowOnShift: - return "Hold shift"; - } - return ""; - }, - [](auto args) { - return args.index; - }, - false); + + SettingWidget::dropdown("Show emote & badge thumbnail on hover", + s.emotesTooltipPreview) + ->addTo(layout); + SettingWidget::dropdown("Emote & badge thumbnail size on hover", s.emoteTooltipScale) ->addTo(layout); diff --git a/src/widgets/settingspages/SettingWidget.cpp b/src/widgets/settingspages/SettingWidget.cpp index 0b9a1a4d..92e3ac1f 100644 --- a/src/widgets/settingspages/SettingWidget.cpp +++ b/src/widgets/settingspages/SettingWidget.cpp @@ -1,6 +1,8 @@ #include "widgets/settingspages/SettingWidget.hpp" -#include "singletons/Settings.hpp" +#include "common/QLogging.hpp" +#include "singletons/Settings.hpp" // IWYU pragma: keep +#include "util/QMagicEnumTagged.hpp" #include "util/RapidJsonSerializeQString.hpp" // IWYU pragma: keep #include "widgets/dialogs/ColorPickerDialog.hpp" #include "widgets/helper/color/ColorButton.hpp" @@ -230,6 +232,83 @@ template SettingWidget *SettingWidget::dropdown( template SettingWidget *SettingWidget::dropdown( const QString &label, EnumStringSetting &setting); +template +SettingWidget *SettingWidget::dropdown(const QString &label, + EnumSetting &setting) +{ + auto *widget = new SettingWidget(label); + + auto *lbl = new QLabel(label % ":"); + auto *combo = new ComboBox; + combo->setFocusPolicy(Qt::StrongFocus); + + for (const auto value : magic_enum::enum_values()) + { + combo->addItem(qmagicenum::enumDisplayNameString(value), + QVariant(static_cast>(value))); + } + + // TODO: this can probably use some other size hint/size strategy + combo->setMinimumWidth(combo->minimumSizeHint().width()); + + 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 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 enumValue = combo->currentData().toInt(&ok); + if (!ok) + { + qCWarning(chatterinoWidget) + << "Combo" << label << " with value" << newText + << "did not contain an intable UserRole data"; + return; + } + + setting.setValue(enumValue); + }); + + return widget; +} + +template SettingWidget *SettingWidget::dropdown( + const QString &label, EnumSetting &setting); +template SettingWidget *SettingWidget::dropdown( + const QString &label, EnumSetting &setting); + SettingWidget *SettingWidget::colorButton(const QString &label, QStringSetting &setting) { diff --git a/src/widgets/settingspages/SettingWidget.hpp b/src/widgets/settingspages/SettingWidget.hpp index 32a3a516..6bd2b6ba 100644 --- a/src/widgets/settingspages/SettingWidget.hpp +++ b/src/widgets/settingspages/SettingWidget.hpp @@ -1,10 +1,6 @@ #pragma once #include "common/ChatterinoSetting.hpp" -#include "common/QLogging.hpp" -#include "util/QMagicEnum.hpp" -#include "util/QMagicEnumTagged.hpp" -#include "widgets/settingspages/GeneralPageView.hpp" #include #include @@ -18,6 +14,9 @@ #include #include +#include +#include + class QFormLayout; namespace chatterino { @@ -57,6 +56,10 @@ public: static SettingWidget *dropdown(const QString &label, EnumStringSetting &setting); + template + static SettingWidget *dropdown(const QString &label, + EnumSetting &setting); + static SettingWidget *colorButton(const QString &label, QStringSetting &setting); static SettingWidget *lineEdit(const QString &label, diff --git a/tests/src/QMagicEnum.cpp b/tests/src/QMagicEnum.cpp index 2af93c17..764e0a93 100644 --- a/tests/src/QMagicEnum.cpp +++ b/tests/src/QMagicEnum.cpp @@ -2,6 +2,7 @@ #include "common/FlagsEnum.hpp" #include "common/Literals.hpp" +#include "common/ThumbnailPreviewMode.hpp" #include "Test.hpp" #include "util/QMagicEnumTagged.hpp" @@ -257,4 +258,8 @@ TEST(QMagicEnumTagged, enumDisplayNameString) auto secondWithSpec = enumName(); ASSERT_EQ(secondWithSpec, u"mysecond.*"); + + ASSERT_EQ( + qmagicenum::enumDisplayNameString(), + u"Don't show"); }