From 0c6b2c611dcf55fcc3b4fe053e0cb693b9e88703 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 23 Feb 2024 13:24:20 +0400 Subject: [PATCH] Add rpl interface to RadiobuttonGroup. --- ui/widgets/checkbox.cpp | 22 +++++++++-- ui/widgets/checkbox.h | 85 +++++++++++++++++++++++------------------ 2 files changed, 66 insertions(+), 41 deletions(-) diff --git a/ui/widgets/checkbox.cpp b/ui/widgets/checkbox.cpp index bc3c6c7..ff7615f 100644 --- a/ui/widgets/checkbox.cpp +++ b/ui/widgets/checkbox.cpp @@ -907,11 +907,25 @@ void RadiobuttonGroup::setValue(int value) { for (const auto button : _buttons) { button->handleNewGroupValue(_value); } - if (const auto callback = _changedCallback) { - callback(_value); + const auto guard = weak_from_this(); + _changes.fire_copy(value); + if (guard.lock()) { + if (const auto callback = _changedCallback) { + callback(_value); + } } } +void RadiobuttonGroup::registerButton(Radiobutton *button) { + if (!base::contains(_buttons, button)) { + _buttons.push_back(button); + } +} + +void RadiobuttonGroup::unregisterButton(Radiobutton *button) { + _buttons.erase(ranges::remove(_buttons, button), _buttons.end()); +} + Radiobutton::Radiobutton( QWidget *parent, const std::shared_ptr &group, @@ -927,7 +941,7 @@ Radiobutton::Radiobutton( st, std::make_unique( radioSt, - (group->hasValue() && group->value() == value))) { + (group->hasValue() && group->current() == value))) { } Radiobutton::Radiobutton( @@ -946,7 +960,7 @@ Radiobutton::Radiobutton( , _value(value) { using namespace rpl::mappers; - checkbox()->setChecked(group->hasValue() && group->value() == value); + checkbox()->setChecked(group->hasValue() && group->current() == value); _group->registerButton(this); checkbox()->checkedChanges( ) | rpl::filter( diff --git a/ui/widgets/checkbox.h b/ui/widgets/checkbox.h index 06da21b..593dc05 100644 --- a/ui/widgets/checkbox.h +++ b/ui/widgets/checkbox.h @@ -191,9 +191,9 @@ public: using ClickHandlerFilter = Fn; void setClickHandlerFilter(ClickHandlerFilter &&filter); - bool checked() const; - rpl::producer checkedChanges() const; - rpl::producer checkedValue() const; + [[nodiscard]] bool checked() const; + [[nodiscard]] rpl::producer checkedChanges() const; + [[nodiscard]] rpl::producer checkedValue() const; enum class NotifyAboutChange { Notify, DontNotify, @@ -204,17 +204,17 @@ public: void finishAnimating(); - QMargins getMargins() const override { + [[nodiscard]] QMargins getMargins() const override { return _st.margin; } - int naturalWidth() const override; + [[nodiscard]] int naturalWidth() const override; void updateCheck() { rtlupdate(checkRect()); } - QRect checkRect() const; + [[nodiscard]] QRect checkRect() const; - not_null checkView() const { + [[nodiscard]] not_null checkView() const { return _check.get(); } @@ -257,7 +257,8 @@ private: class Radiobutton; -class RadiobuttonGroup { +class RadiobuttonGroup + : public std::enable_shared_from_this { public: RadiobuttonGroup() = default; RadiobuttonGroup(int value) : _value(value), _hasValue(true) { @@ -266,29 +267,32 @@ public: void setChangedCallback(Fn callback) { _changedCallback = std::move(callback); } + [[nodiscard]] rpl::producer changes() const { + return _changes.events(); + } + [[nodiscard]] rpl::producer value() const { + return hasValue() + ? _changes.events_starting_with_copy(_value) + : changes(); + } - bool hasValue() const { + [[nodiscard]] bool hasValue() const { return _hasValue; } - int value() const { + [[nodiscard]] int current() const { return _value; } void setValue(int value); private: friend class Radiobutton; - void registerButton(Radiobutton *button) { - if (!base::contains(_buttons, button)) { - _buttons.push_back(button); - } - } - void unregisterButton(Radiobutton *button) { - _buttons.erase(std::remove(_buttons.begin(), _buttons.end(), button), _buttons.end()); - } + void registerButton(Radiobutton *button); + void unregisterButton(Radiobutton *button); int _value = 0; bool _hasValue = false; Fn _changedCallback; + rpl::event_stream _changes; std::vector _buttons; }; @@ -340,35 +344,42 @@ template class Radioenum; template -class RadioenumGroup { +class RadioenumGroup : public RadiobuttonGroup { + using Parent = RadiobuttonGroup; + + [[nodiscard]] static Enum Cast(int value) { + return static_cast(value); + } + public: RadioenumGroup() = default; - RadioenumGroup(Enum value) : _group(static_cast(value)) { + RadioenumGroup(Enum value) : Parent(static_cast(value)) { } template void setChangedCallback(Callback &&callback) { - _group.setChangedCallback([callback](int value) { - callback(static_cast(value)); + Parent::setChangedCallback([copy = std::move(callback)](int value) { + copy(Cast(value)); }); } - bool hasValue() const { - return _group.hasValue(); + [[nodiscard]] rpl::producer changes() const { + return Parent::changes() | rpl::map(Cast); } - Enum value() const { - return static_cast(_group.value()); + [[nodiscard]] rpl::producer value() const { + return Parent::value() | rpl::map(Cast); + } + [[nodiscard]] Enum current() const { + return Cast(Parent::current()); } void setValue(Enum value) { - _group.setValue(static_cast(value)); + Parent::setValue(static_cast(value)); } private: template friend class Radioenum; - RadiobuttonGroup _group; - }; template @@ -382,7 +393,7 @@ public: const style::Checkbox &st = st::defaultCheckbox) : Radiobutton( parent, - std::shared_ptr(group, &group->_group), + group->shared_from_this(), static_cast(value), text, st) { @@ -394,13 +405,13 @@ public: const QString &text, const style::Checkbox &st, std::unique_ptr check) - : Radiobutton( - parent, - std::shared_ptr(group, &group->_group), - static_cast(value), - text, - st, - std::move(check)) { + : Radiobutton( + parent, + group->shared_from_this(), + static_cast(value), + text, + st, + std::move(check)) { } };