Fix crash in radiobutton destruction.

It crashed if the button was destroyed from group _changedCallback.
This commit is contained in:
John Preston 2018-12-05 13:55:56 +04:00
parent b10ccce44a
commit efe3dfad5c
13 changed files with 165 additions and 119 deletions

View File

@ -569,17 +569,20 @@ void ProxiesBox::setupContent() {
} }
refreshProxyForCalls(); refreshProxyForCalls();
}); });
subscribe(_tryIPv6->checkedChanged, [=](bool checked) { _tryIPv6->checkedChanges(
) | rpl::start_with_next([=](bool checked) {
_controller->setTryIPv6(checked); _controller->setTryIPv6(checked);
}); }, _tryIPv6->lifetime());
_controller->proxySettingsValue( _controller->proxySettingsValue(
) | rpl::start_with_next([=](ProxyData::Settings value) { ) | rpl::start_with_next([=](ProxyData::Settings value) {
_proxySettings->setValue(value); _proxySettings->setValue(value);
}, inner->lifetime()); }, inner->lifetime());
subscribe(_proxyForCalls->entity()->checkedChanged, [=](bool checked) { _proxyForCalls->entity()->checkedChanges(
) | rpl::start_with_next([=](bool checked) {
_controller->setProxyForCalls(checked); _controller->setProxyForCalls(checked);
}); }, _proxyForCalls->lifetime());
if (_rows.empty()) { if (_rows.empty()) {
createNoRowsLabel(); createNoRowsLabel();

View File

@ -236,9 +236,12 @@ void EditAdminBox::prepare() {
auto addCheckbox = [&](Flags flags, const QString &text) { auto addCheckbox = [&](Flags flags, const QString &text) {
const auto checked = (prepareFlags & flags) != 0; const auto checked = (prepareFlags & flags) != 0;
auto control = addControl(object_ptr<Ui::Checkbox>(this, text, checked, st::rightsCheckbox, st::rightsToggle), st::rightsToggleMargin); auto control = addControl(object_ptr<Ui::Checkbox>(this, text, checked, st::rightsCheckbox, st::rightsToggle), st::rightsToggleMargin);
subscribe(control->checkedChanged, [this, control](bool checked) { control->checkedChanges(
InvokeQueued(this, [this, control] { applyDependencies(control); }); ) | rpl::start_with_next([=](bool checked) {
}); InvokeQueued(this, [=] {
applyDependencies(control);
});
}, control->lifetime());
if (!channel()->amCreator()) { if (!channel()->amCreator()) {
if (!(channel()->adminRights() & flags)) { if (!(channel()->adminRights() & flags)) {
control->setDisabled(true); // Grey out options that we don't have ourselves. control->setDisabled(true); // Grey out options that we don't have ourselves.
@ -267,11 +270,14 @@ void EditAdminBox::prepare() {
auto addAdmins = _checkboxes.find(Flag::f_add_admins); auto addAdmins = _checkboxes.find(Flag::f_add_admins);
if (addAdmins != _checkboxes.end()) { if (addAdmins != _checkboxes.end()) {
_aboutAddAdmins = addControl(object_ptr<Ui::FlatLabel>(this, st::boxLabel), st::rightsAboutMargin); _aboutAddAdmins = addControl(
object_ptr<Ui::FlatLabel>(this, st::boxLabel),
st::rightsAboutMargin);
Assert(addAdmins != _checkboxes.end()); Assert(addAdmins != _checkboxes.end());
subscribe(addAdmins->second->checkedChanged, [this](bool checked) { addAdmins->second->checkedChanges(
) | rpl::start_with_next([=](bool checked) {
refreshAboutAddAdminsText(); refreshAboutAddAdminsText();
}); }, addAdmins->second->lifetime());
refreshAboutAddAdminsText(); refreshAboutAddAdminsText();
} }
@ -354,12 +360,15 @@ void EditRestrictedBox::prepare() {
auto prepareRights = (_oldRights.c_channelBannedRights().vflags.v ? _oldRights : DefaultRights(channel())); auto prepareRights = (_oldRights.c_channelBannedRights().vflags.v ? _oldRights : DefaultRights(channel()));
_until = prepareRights.c_channelBannedRights().vuntil_date.v; _until = prepareRights.c_channelBannedRights().vuntil_date.v;
auto addCheckbox = [this, &prepareRights](Flags flags, const QString &text) { auto addCheckbox = [&](Flags flags, const QString &text) {
auto checked = (prepareRights.c_channelBannedRights().vflags.v & flags) == 0; auto checked = (prepareRights.c_channelBannedRights().vflags.v & flags) == 0;
auto control = addControl(object_ptr<Ui::Checkbox>(this, text, checked, st::rightsCheckbox, st::rightsToggle), st::rightsToggleMargin); auto control = addControl(object_ptr<Ui::Checkbox>(this, text, checked, st::rightsCheckbox, st::rightsToggle), st::rightsToggleMargin);
subscribe(control->checkedChanged, [this, control](bool checked) { control->checkedChanges(
InvokeQueued(this, [this, control] { applyDependencies(control); }); ) | rpl::start_with_next([=](bool checked) {
}); InvokeQueued(this, [=] {
applyDependencies(control);
});
}, control->lifetime());
if (!canSave()) { if (!canSave()) {
control->setDisabled(true); control->setDisabled(true);
} }

View File

@ -127,15 +127,24 @@ void AddBotToGroup(not_null<UserData*> bot, not_null<PeerData*> chat) {
// return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition; // return mapFromGlobal(QCursor::pos()) - _st.rippleAreaPosition;
//} //}
class EditChatAdminsBoxController::LabeledCheckbox : public TWidget, private base::Subscriber { class EditChatAdminsBoxController::LabeledCheckbox : public Ui::RpWidget {
public: public:
LabeledCheckbox(QWidget *parent, const QString &text, bool checked = false, const style::Checkbox &st = st::defaultCheckbox, const style::Check &checkSt = st::defaultCheck); LabeledCheckbox(
QWidget *parent,
base::Observable<bool> checkedChanged; const QString &text,
bool checked = false,
const style::Checkbox &st = st::defaultCheckbox,
const style::Check &checkSt = st::defaultCheck);
bool checked() const { bool checked() const {
return _checkbox->checked(); return _checkbox->checked();
} }
rpl::producer<bool> checkedChanges() const {
return _checkbox->checkedChanges();
}
rpl::producer<bool> checkedValue() const {
return _checkbox->checkedValue();
}
void setLabelText( void setLabelText(
bool checked, bool checked,
@ -605,9 +614,8 @@ EditChatAdminsBoxController::LabeledCheckbox::LabeledCheckbox(
bool checked, bool checked,
const style::Checkbox &st, const style::Checkbox &st,
const style::Check &checkSt) const style::Check &checkSt)
: TWidget(parent) : RpWidget(parent)
, _checkbox(this, text, checked, st, checkSt) { , _checkbox(this, text, checked, st, checkSt) {
subscribe(_checkbox->checkedChanged, [this](bool value) { checkedChanged.notify(value, true); });
} }
void EditChatAdminsBoxController::LabeledCheckbox::setLabelText( void EditChatAdminsBoxController::LabeledCheckbox::setLabelText(
@ -676,7 +684,8 @@ void EditChatAdminsBoxController::prepare() {
})); }));
} }
subscribe(_allAdmins->checkedChanged, [this](bool checked) { _allAdmins->checkedChanges(
) | rpl::start_with_next([=](bool checked) {
delegate()->peerListSetSearchMode(checked ? PeerListSearchMode::Disabled : PeerListSearchMode::Enabled); delegate()->peerListSetSearchMode(checked ? PeerListSearchMode::Disabled : PeerListSearchMode::Enabled);
for (auto i = 0, count = delegate()->peerListFullRowsCount(); i != count; ++i) { for (auto i = 0, count = delegate()->peerListFullRowsCount(); i != count; ++i) {
auto row = delegate()->peerListRowAt(i); auto row = delegate()->peerListRowAt(i);
@ -687,7 +696,7 @@ void EditChatAdminsBoxController::prepare() {
row->setDisabledState(PeerListRow::State::Active); row->setDisabledState(PeerListRow::State::Active);
} }
} }
}); }, _allAdmins->lifetime());
} }
void EditChatAdminsBoxController::createAllAdminsCheckbox() { void EditChatAdminsBoxController::createAllAdminsCheckbox() {

View File

@ -464,8 +464,7 @@ not_null<Ui::Checkbox*> SettingsWidget::addOption(
((readData().types & types) == types), ((readData().types & types) == types),
st::defaultBoxCheckbox), st::defaultBoxCheckbox),
st::exportSettingPadding); st::exportSettingPadding);
base::ObservableViewer( checkbox->checkedChanges(
checkbox->checkedChanged
) | rpl::start_with_next([=](bool checked) { ) | rpl::start_with_next([=](bool checked) {
changeData([&](Settings &data) { changeData([&](Settings &data) {
if (checked) { if (checked) {
@ -474,7 +473,7 @@ not_null<Ui::Checkbox*> SettingsWidget::addOption(
data.types &= ~types; data.types &= ~types;
} }
}); });
}, lifetime()); }, checkbox->lifetime());
return checkbox; return checkbox;
} }
@ -509,8 +508,7 @@ void SettingsWidget::addChatOption(
st::defaultBoxCheckbox), st::defaultBoxCheckbox),
st::exportSubSettingPadding)); st::exportSubSettingPadding));
base::ObservableViewer( onlyMy->entity()->checkedChanges(
onlyMy->entity()->checkedChanged
) | rpl::start_with_next([=](bool checked) { ) | rpl::start_with_next([=](bool checked) {
changeData([&](Settings &data) { changeData([&](Settings &data) {
if (checked) { if (checked) {
@ -519,13 +517,9 @@ void SettingsWidget::addChatOption(
data.fullChats |= types; data.fullChats |= types;
} }
}); });
}, checkbox->lifetime()); }, onlyMy->lifetime());
onlyMy->toggleOn(base::ObservableViewer( onlyMy->toggleOn(checkbox->checkedValue());
checkbox->checkedChanged
));
onlyMy->toggle(checkbox->checked(), anim::type::instant);
if (types & (Type::PublicGroups | Type::PublicChannels)) { if (types & (Type::PublicGroups | Type::PublicChannels)) {
onlyMy->entity()->setChecked(true); onlyMy->entity()->setChecked(true);
@ -568,8 +562,7 @@ void SettingsWidget::addMediaOption(
((readData().media.types & type) == type), ((readData().media.types & type) == type),
st::defaultBoxCheckbox), st::defaultBoxCheckbox),
st::exportSettingPadding); st::exportSettingPadding);
base::ObservableViewer( checkbox->checkedChanges(
checkbox->checkedChanged
) | rpl::start_with_next([=](bool checked) { ) | rpl::start_with_next([=](bool checked) {
changeData([&](Settings &data) { changeData([&](Settings &data) {
if (checked) { if (checked) {
@ -578,7 +571,7 @@ void SettingsWidget::addMediaOption(
data.media.types &= ~type; data.media.types &= ~type;
} }
}); });
}, lifetime()); }, checkbox->lifetime());
} }
void SettingsWidget::addSizeSlider( void SettingsWidget::addSizeSlider(

View File

@ -23,13 +23,16 @@ public:
bool checked() const { bool checked() const {
return _check->checked(); return _check->checked();
} }
base::Observable<bool> checkedChanged; rpl::producer<bool> checkedChanges() const;
rpl::producer<bool> checkedValue() const;
enum class NotifyAboutChange { enum class NotifyAboutChange {
Notify, Notify,
DontNotify, DontNotify,
}; };
void setChecked(bool checked, NotifyAboutChange notify = NotifyAboutChange::Notify); void setChecked(
bool checked,
NotifyAboutChange notify = NotifyAboutChange::Notify);
void finishAnimating(); void finishAnimating();
@ -48,6 +51,7 @@ protected:
private: private:
const style::Checkbox &_st; const style::Checkbox &_st;
std::unique_ptr<Ui::AbstractCheckView> _check; std::unique_ptr<Ui::AbstractCheckView> _check;
rpl::event_stream<bool> _checkedChanges;
QRect _checkRect; QRect _checkRect;
@ -73,11 +77,19 @@ UserCheckbox::UserCheckbox(QWidget *parent, not_null<UserData*> user, bool check
_checkRect = { QPoint(_st.margin.left(), (st::contactsPhotoSize - checkSize.height()) / 2), checkSize }; _checkRect = { QPoint(_st.margin.left(), (st::contactsPhotoSize - checkSize.height()) / 2), checkSize };
} }
rpl::producer<bool> UserCheckbox::checkedChanges() const {
return _checkedChanges.events();
}
rpl::producer<bool> UserCheckbox::checkedValue() const {
return _checkedChanges.events_starting_with(checked());
}
void UserCheckbox::setChecked(bool checked, NotifyAboutChange notify) { void UserCheckbox::setChecked(bool checked, NotifyAboutChange notify) {
if (_check->checked() != checked) { if (_check->checked() != checked) {
_check->setChecked(checked, anim::type::normal); _check->setChecked(checked, anim::type::normal);
if (notify == NotifyAboutChange::Notify) { if (notify == NotifyAboutChange::Notify) {
checkedChanged.notify(checked, true); _checkedChanges.fire_copy(checked);
} }
} }
} }
@ -132,9 +144,14 @@ QPoint UserCheckbox::prepareRippleStartPosition() const {
} // namespace } // namespace
class FilterBox::Inner : public TWidget, private base::Subscriber { class FilterBox::Inner : public Ui::RpWidget {
public: public:
Inner(QWidget *parent, not_null<ChannelData*> channel, const std::vector<not_null<UserData*>> &admins, const FilterValue &filter, Fn<void()> changedCallback); Inner(
QWidget *parent,
not_null<ChannelData*> channel,
const std::vector<not_null<UserData*>> &admins,
const FilterValue &filter,
Fn<void()> changedCallback);
template <typename Widget> template <typename Widget>
QPointer<Widget> addRow(object_ptr<Widget> widget, int marginTop) { QPointer<Widget> addRow(object_ptr<Widget> widget, int marginTop) {
@ -155,11 +172,15 @@ protected:
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
private: private:
void createControls(const std::vector<not_null<UserData*>> &admins, const FilterValue &filter); void createControls(
const std::vector<not_null<UserData*>> &admins,
const FilterValue &filter);
void createAllActionsCheckbox(const FilterValue &filter); void createAllActionsCheckbox(const FilterValue &filter);
void createActionsCheckboxes(const FilterValue &filter); void createActionsCheckboxes(const FilterValue &filter);
void createAllUsersCheckbox(const FilterValue &filter); void createAllUsersCheckbox(const FilterValue &filter);
void createAdminsCheckboxes(const std::vector<not_null<UserData*>> &admins, const FilterValue &filter); void createAdminsCheckboxes(
const std::vector<not_null<UserData*>> &admins,
const FilterValue &filter);
not_null<ChannelData*> _channel; not_null<ChannelData*> _channel;
@ -180,7 +201,13 @@ private:
}; };
FilterBox::Inner::Inner(QWidget *parent, not_null<ChannelData*> channel, const std::vector<not_null<UserData*>> &admins, const FilterValue &filter, Fn<void()> changedCallback) : TWidget(parent) FilterBox::Inner::Inner(
QWidget *parent,
not_null<ChannelData*> channel,
const std::vector<not_null<UserData*>> &admins,
const FilterValue &filter,
Fn<void()> changedCallback)
: RpWidget(parent)
, _channel(channel) , _channel(channel)
, _changedCallback(std::move(changedCallback)) { , _changedCallback(std::move(changedCallback)) {
createControls(admins, filter); createControls(admins, filter);
@ -196,7 +223,8 @@ void FilterBox::Inner::createControls(const std::vector<not_null<UserData*>> &ad
void FilterBox::Inner::createAllActionsCheckbox(const FilterValue &filter) { void FilterBox::Inner::createAllActionsCheckbox(const FilterValue &filter) {
auto checked = (filter.flags == 0); auto checked = (filter.flags == 0);
_allFlags = addRow(object_ptr<Ui::Checkbox>(this, lang(lng_admin_log_filter_all_actions), checked, st::adminLogFilterCheckbox), st::adminLogFilterCheckbox.margin.top()); _allFlags = addRow(object_ptr<Ui::Checkbox>(this, lang(lng_admin_log_filter_all_actions), checked, st::adminLogFilterCheckbox), st::adminLogFilterCheckbox.margin.top());
subscribe(_allFlags->checkedChanged, [this](bool checked) { _allFlags->checkedChanges(
) | rpl::start_with_next([=](bool checked) {
if (!std::exchange(_restoringInvariant, true)) { if (!std::exchange(_restoringInvariant, true)) {
auto allChecked = _allFlags->checked(); auto allChecked = _allFlags->checked();
for_const (auto &&checkbox, _filterFlags) { for_const (auto &&checkbox, _filterFlags) {
@ -207,7 +235,7 @@ void FilterBox::Inner::createAllActionsCheckbox(const FilterValue &filter) {
_changedCallback(); _changedCallback();
} }
} }
}); }, _allFlags->lifetime());
} }
void FilterBox::Inner::createActionsCheckboxes(const FilterValue &filter) { void FilterBox::Inner::createActionsCheckboxes(const FilterValue &filter) {
@ -217,7 +245,8 @@ void FilterBox::Inner::createActionsCheckboxes(const FilterValue &filter) {
auto checked = (filter.flags == 0) || (filter.flags & flag); auto checked = (filter.flags == 0) || (filter.flags & flag);
auto checkbox = addRow(object_ptr<Ui::Checkbox>(this, std::move(text), checked, st::defaultBoxCheckbox), st::adminLogFilterLittleSkip); auto checkbox = addRow(object_ptr<Ui::Checkbox>(this, std::move(text), checked, st::defaultBoxCheckbox), st::adminLogFilterLittleSkip);
_filterFlags.insert(flag, checkbox); _filterFlags.insert(flag, checkbox);
subscribe(checkbox->checkedChanged, [this](bool checked) { checkbox->checkedChanges(
) | rpl::start_with_next([=](bool checked) {
if (!std::exchange(_restoringInvariant, true)) { if (!std::exchange(_restoringInvariant, true)) {
auto allChecked = true; auto allChecked = true;
for_const (auto &&checkbox, _filterFlags) { for_const (auto &&checkbox, _filterFlags) {
@ -232,7 +261,7 @@ void FilterBox::Inner::createActionsCheckboxes(const FilterValue &filter) {
_changedCallback(); _changedCallback();
} }
} }
}); }, checkbox->lifetime());
}; };
auto isGroup = _channel->isMegagroup(); auto isGroup = _channel->isMegagroup();
if (isGroup) { if (isGroup) {
@ -251,7 +280,8 @@ void FilterBox::Inner::createActionsCheckboxes(const FilterValue &filter) {
void FilterBox::Inner::createAllUsersCheckbox(const FilterValue &filter) { void FilterBox::Inner::createAllUsersCheckbox(const FilterValue &filter) {
_allUsers = addRow(object_ptr<Ui::Checkbox>(this, lang(lng_admin_log_filter_all_admins), filter.allUsers, st::adminLogFilterCheckbox), st::adminLogFilterSkip); _allUsers = addRow(object_ptr<Ui::Checkbox>(this, lang(lng_admin_log_filter_all_admins), filter.allUsers, st::adminLogFilterCheckbox), st::adminLogFilterSkip);
subscribe(_allUsers->checkedChanged, [this](bool checked) { _allUsers->checkedChanges(
) | rpl::start_with_next([=](bool checked) {
if (checked && !std::exchange(_restoringInvariant, true)) { if (checked && !std::exchange(_restoringInvariant, true)) {
for_const (auto &&checkbox, _admins) { for_const (auto &&checkbox, _admins) {
checkbox->setChecked(true); checkbox->setChecked(true);
@ -261,14 +291,15 @@ void FilterBox::Inner::createAllUsersCheckbox(const FilterValue &filter) {
_changedCallback(); _changedCallback();
} }
} }
}); }, _allUsers->lifetime());
} }
void FilterBox::Inner::createAdminsCheckboxes(const std::vector<not_null<UserData*>> &admins, const FilterValue &filter) { void FilterBox::Inner::createAdminsCheckboxes(const std::vector<not_null<UserData*>> &admins, const FilterValue &filter) {
for (auto user : admins) { for (auto user : admins) {
auto checked = filter.allUsers || base::contains(filter.admins, user); auto checked = filter.allUsers || base::contains(filter.admins, user);
auto checkbox = addRow(object_ptr<UserCheckbox>(this, user, checked), st::adminLogFilterLittleSkip); auto checkbox = addRow(object_ptr<UserCheckbox>(this, user, checked), st::adminLogFilterLittleSkip);
subscribe(checkbox->checkedChanged, [this](bool checked) { checkbox->checkedChanges(
) | rpl::start_with_next([=](bool checked) {
if (!std::exchange(_restoringInvariant, true)) { if (!std::exchange(_restoringInvariant, true)) {
auto allChecked = true; auto allChecked = true;
for_const (auto &&checkbox, _admins) { for_const (auto &&checkbox, _admins) {
@ -285,7 +316,7 @@ void FilterBox::Inner::createAdminsCheckboxes(const std::vector<not_null<UserDat
_changedCallback(); _changedCallback();
} }
} }
}); }, checkbox->lifetime());
_admins.insert(user, checkbox); _admins.insert(user, checkbox);
} }
} }

View File

@ -191,9 +191,7 @@ bool SectionWithToggle::toggled() const {
rpl::producer<bool> SectionWithToggle::toggledValue() const { rpl::producer<bool> SectionWithToggle::toggledValue() const {
if (_toggle) { if (_toggle) {
return rpl::single( return _toggle->checkedValue();
_toggle->checked()
) | rpl::then(base::ObservableViewer(_toggle->checkedChanged));
} }
return rpl::never<bool>(); return rpl::never<bool>();
} }

View File

@ -296,8 +296,7 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
Local::writeSettings(); Local::writeSettings();
}; };
base::ObservableViewer( tray->checkedChanges(
tray->checkedChanged
) | rpl::filter([=](bool checked) { ) | rpl::filter([=](bool checked) {
return (checked != trayEnabled()); return (checked != trayEnabled());
}) | rpl::start_with_next([=](bool checked) { }) | rpl::start_with_next([=](bool checked) {
@ -309,8 +308,7 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
}, tray->lifetime()); }, tray->lifetime());
if (taskbar) { if (taskbar) {
base::ObservableViewer( taskbar->checkedChanges(
taskbar->checkedChanged
) | rpl::filter([=](bool checked) { ) | rpl::filter([=](bool checked) {
return (checked != taskbarEnabled()); return (checked != taskbarEnabled());
}) | rpl::start_with_next([=](bool checked) { }) | rpl::start_with_next([=](bool checked) {
@ -338,8 +336,7 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
lng_settings_add_sendto, lng_settings_add_sendto,
cSendToMenu()); cSendToMenu());
base::ObservableViewer( autostart->checkedChanges(
autostart->checkedChanged
) | rpl::filter([](bool checked) { ) | rpl::filter([](bool checked) {
return (checked != cAutoStart()); return (checked != cAutoStart());
}) | rpl::start_with_next([=](bool checked) { }) | rpl::start_with_next([=](bool checked) {
@ -354,13 +351,8 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
} }
}, autostart->lifetime()); }, autostart->lifetime());
minimized->toggleOn(rpl::single( minimized->toggleOn(autostart->checkedValue());
autostart->checked() minimized->entity()->checkedChanges(
) | rpl::then(base::ObservableViewer(
autostart->checkedChanged
)));
base::ObservableViewer(
minimized->entity()->checkedChanged
) | rpl::filter([=](bool checked) { ) | rpl::filter([=](bool checked) {
return (checked != minimizedToggled()); return (checked != minimizedToggled());
}) | rpl::start_with_next([=](bool checked) { }) | rpl::start_with_next([=](bool checked) {
@ -380,8 +372,7 @@ void SetupTrayContent(not_null<Ui::VerticalLayout*> container) {
minimized->entity()->setChecked(minimizedToggled()); minimized->entity()->setChecked(minimizedToggled());
}, minimized->lifetime()); }, minimized->lifetime());
base::ObservableViewer( sendto->checkedChanges(
sendto->checkedChanged
) | rpl::filter([](bool checked) { ) | rpl::filter([](bool checked) {
return (checked != cSendToMenu()); return (checked != cSendToMenu());
}) | rpl::start_with_next([](bool checked) { }) | rpl::start_with_next([](bool checked) {

View File

@ -441,11 +441,10 @@ void SetupStickersEmoji(not_null<Ui::VerticalLayout*> container) {
st::settingsCheckbox); st::settingsCheckbox);
}; };
const auto add = [&](LangKey label, bool checked, auto &&handle) { const auto add = [&](LangKey label, bool checked, auto &&handle) {
base::ObservableViewer( inner->add(
inner->add( checkbox(label, checked),
checkbox(label, checked), st::settingsCheckboxPadding
st::settingsCheckboxPadding )->checkedChanges(
)->checkedChanged
) | rpl::start_with_next( ) | rpl::start_with_next(
std::move(handle), std::move(handle),
inner->lifetime()); inner->lifetime());
@ -670,8 +669,7 @@ void SetupChatBackground(not_null<Ui::VerticalLayout*> container) {
st::settingsCheckbox), st::settingsCheckbox),
st::settingsSendTypePadding)); st::settingsSendTypePadding));
base::ObservableViewer( tile->checkedChanges(
tile->checkedChanged
) | rpl::start_with_next([](bool checked) { ) | rpl::start_with_next([](bool checked) {
Window::Theme::Background()->setTile(checked); Window::Theme::Background()->setTile(checked);
}, tile->lifetime()); }, tile->lifetime());
@ -695,8 +693,7 @@ void SetupChatBackground(not_null<Ui::VerticalLayout*> container) {
return (Global::AdaptiveChatLayout() == Adaptive::ChatLayout::Wide); return (Global::AdaptiveChatLayout() == Adaptive::ChatLayout::Wide);
})); }));
base::ObservableViewer( adaptive->entity()->checkedChanges(
adaptive->entity()->checkedChanged
) | rpl::start_with_next([](bool checked) { ) | rpl::start_with_next([](bool checked) {
Global::SetAdaptiveForWide(checked); Global::SetAdaptiveForWide(checked);
Adaptive::Changed().notify(); Adaptive::Changed().notify();
@ -986,15 +983,14 @@ void SetupSupport(not_null<Ui::VerticalLayout*> container) {
AddSkip(inner, st::settingsCheckboxesSkip); AddSkip(inner, st::settingsCheckboxesSkip);
base::ObservableViewer( inner->add(
inner->add( object_ptr<Ui::Checkbox>(
object_ptr<Ui::Checkbox>( inner,
inner, "Enable templates autocomplete",
"Enable templates autocomplete", Auth().settings().supportTemplatesAutocomplete(),
Auth().settings().supportTemplatesAutocomplete(), st::settingsCheckbox),
st::settingsCheckbox), st::settingsSendTypePadding
st::settingsSendTypePadding )->checkedChanges(
)->checkedChanged
) | rpl::start_with_next([=](bool checked) { ) | rpl::start_with_next([=](bool checked) {
Auth().settings().setSupportTemplatesAutocomplete(checked); Auth().settings().setSupportTemplatesAutocomplete(checked);
Local::writeUserSettings(); Local::writeUserSettings();

View File

@ -594,8 +594,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
Local::writeUserSettings(); Local::writeUserSettings();
Auth().notifications().settingsChanged().notify(change); Auth().notifications().settingsChanged().notify(change);
}; };
base::ObservableViewer( desktop->checkedChanges(
desktop->checkedChanged
) | rpl::filter([](bool checked) { ) | rpl::filter([](bool checked) {
return (checked != Global::DesktopNotify()); return (checked != Global::DesktopNotify());
}) | rpl::start_with_next([=](bool checked) { }) | rpl::start_with_next([=](bool checked) {
@ -603,8 +602,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
changed(Change::DesktopEnabled); changed(Change::DesktopEnabled);
}, desktop->lifetime()); }, desktop->lifetime());
base::ObservableViewer( name->entity()->checkedChanges(
name->entity()->checkedChanged
) | rpl::map([=](bool checked) { ) | rpl::map([=](bool checked) {
if (!checked) { if (!checked) {
return dbinvShowNothing; return dbinvShowNothing;
@ -619,8 +617,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
changed(Change::ViewParams); changed(Change::ViewParams);
}, name->lifetime()); }, name->lifetime());
base::ObservableViewer( preview->entity()->checkedChanges(
preview->entity()->checkedChanged
) | rpl::map([=](bool checked) { ) | rpl::map([=](bool checked) {
if (checked) { if (checked) {
return dbinvShowPreview; return dbinvShowPreview;
@ -635,8 +632,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
changed(Change::ViewParams); changed(Change::ViewParams);
}, preview->lifetime()); }, preview->lifetime());
base::ObservableViewer( sound->checkedChanges(
sound->checkedChanged
) | rpl::filter([](bool checked) { ) | rpl::filter([](bool checked) {
return (checked != Global::SoundNotify()); return (checked != Global::SoundNotify());
}) | rpl::start_with_next([=](bool checked) { }) | rpl::start_with_next([=](bool checked) {
@ -644,8 +640,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
changed(Change::SoundEnabled); changed(Change::SoundEnabled);
}, sound->lifetime()); }, sound->lifetime());
base::ObservableViewer( muted->checkedChanges(
muted->checkedChanged
) | rpl::filter([](bool checked) { ) | rpl::filter([](bool checked) {
return (checked != Auth().settings().includeMutedCounter()); return (checked != Auth().settings().includeMutedCounter());
}) | rpl::start_with_next([=](bool checked) { }) | rpl::start_with_next([=](bool checked) {
@ -653,14 +648,13 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
changed(Change::IncludeMuted); changed(Change::IncludeMuted);
}, muted->lifetime()); }, muted->lifetime());
base::ObservableViewer( count->checkedChanges(
count->checkedChanged
) | rpl::filter([](bool checked) { ) | rpl::filter([](bool checked) {
return (checked != Auth().settings().countUnreadMessages()); return (checked != Auth().settings().countUnreadMessages());
}) | rpl::start_with_next([=](bool checked) { }) | rpl::start_with_next([=](bool checked) {
Auth().settings().setCountUnreadMessages(checked); Auth().settings().setCountUnreadMessages(checked);
changed(Change::CountMessages); changed(Change::CountMessages);
}, muted->lifetime()); }, count->lifetime());
base::ObservableViewer( base::ObservableViewer(
Auth().notifications().settingsChanged() Auth().notifications().settingsChanged()
@ -679,8 +673,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
}, desktop->lifetime()); }, desktop->lifetime());
if (native) { if (native) {
base::ObservableViewer( native->checkedChanges(
native->checkedChanged
) | rpl::filter([](bool checked) { ) | rpl::filter([](bool checked) {
return (checked != Global::NativeNotifications()); return (checked != Global::NativeNotifications());
}) | rpl::start_with_next([=](bool checked) { }) | rpl::start_with_next([=](bool checked) {

View File

@ -66,12 +66,17 @@ void AbstractButton::mouseMoveEvent(QMouseEvent *e) {
void AbstractButton::mouseReleaseEvent(QMouseEvent *e) { void AbstractButton::mouseReleaseEvent(QMouseEvent *e) {
if (_state & StateFlag::Down) { if (_state & StateFlag::Down) {
auto was = _state; const auto was = _state;
_state &= ~State(StateFlag::Down); _state &= ~State(StateFlag::Down);
auto weak = make_weak(this);
onStateChanged(was, StateChangeSource::ByPress); onStateChanged(was, StateChangeSource::ByPress);
if (!weak) {
return;
}
if (was & StateFlag::Over) { if (was & StateFlag::Over) {
_modifiers = e->modifiers(); _modifiers = e->modifiers();
auto weak = make_weak(this);
if (const auto callback = _clickedCallback) { if (const auto callback = _clickedCallback) {
callback(); callback();
} else { } else {

View File

@ -428,6 +428,14 @@ bool Checkbox::checked() const {
return _check->checked(); return _check->checked();
} }
rpl::producer<bool> Checkbox::checkedChanges() const {
return _checkedChanges.events();
}
rpl::producer<bool> Checkbox::checkedValue() const {
return _checkedChanges.events_starting_with(checked());
}
void Checkbox::resizeToText() { void Checkbox::resizeToText() {
if (_st.width <= 0) { if (_st.width <= 0) {
resizeToWidth(_text.maxWidth() - _st.width); resizeToWidth(_text.maxWidth() - _st.width);
@ -440,7 +448,7 @@ void Checkbox::setChecked(bool checked, NotifyAboutChange notify) {
if (_check->checked() != checked) { if (_check->checked() != checked) {
_check->setChecked(checked, anim::type::normal); _check->setChecked(checked, anim::type::normal);
if (notify == NotifyAboutChange::Notify) { if (notify == NotifyAboutChange::Notify) {
checkedChanged.notify(checked, true); _checkedChanges.fire_copy(checked);
} }
} }
} }
@ -635,19 +643,24 @@ Radiobutton::Radiobutton(
std::move(check)) std::move(check))
, _group(group) , _group(group)
, _value(value) { , _value(value) {
using namespace rpl::mappers;
checkbox()->setChecked(group->hasValue() && group->value() == value); checkbox()->setChecked(group->hasValue() && group->value() == value);
_group->registerButton(this); _group->registerButton(this);
subscribe(checkbox()->checkedChanged, [this](bool checked) { checkbox()->checkedChanges(
if (checked) { ) | rpl::filter(
_group->setValue(_value); _1
} ) | rpl::start_with_next([=] {
}); _group->setValue(_value);
}, lifetime());
} }
void Radiobutton::handleNewGroupValue(int value) { void Radiobutton::handleNewGroupValue(int value) {
auto checked = (value == _value); auto checked = (value == _value);
if (checkbox()->checked() != checked) { if (checkbox()->checked() != checked) {
checkbox()->setChecked(checked, Ui::Checkbox::NotifyAboutChange::DontNotify); checkbox()->setChecked(
checked,
Ui::Checkbox::NotifyAboutChange::DontNotify);
} }
} }

View File

@ -156,12 +156,15 @@ public:
void setCheckAlignment(style::align alignment); void setCheckAlignment(style::align alignment);
bool checked() const; bool checked() const;
rpl::producer<bool> checkedChanges() const;
rpl::producer<bool> checkedValue() const;
enum class NotifyAboutChange { enum class NotifyAboutChange {
Notify, Notify,
DontNotify, DontNotify,
}; };
void setChecked(bool checked, NotifyAboutChange notify = NotifyAboutChange::Notify); void setChecked(
base::Observable<bool> checkedChanged; bool checked,
NotifyAboutChange notify = NotifyAboutChange::Notify);
void finishAnimating(); void finishAnimating();
@ -192,6 +195,7 @@ private:
const style::Checkbox &_st; const style::Checkbox &_st;
std::unique_ptr<AbstractCheckView> _check; std::unique_ptr<AbstractCheckView> _check;
rpl::event_stream<bool> _checkedChanges;
QPixmap _checkCache; QPixmap _checkCache;
Text _text; Text _text;
@ -237,7 +241,7 @@ private:
}; };
class Radiobutton : public Checkbox, private base::Subscriber { class Radiobutton : public Checkbox {
public: public:
Radiobutton( Radiobutton(
QWidget *parent, QWidget *parent,
@ -261,8 +265,10 @@ protected:
private: private:
// Hide the names from Checkbox. // Hide the names from Checkbox.
bool checked() const; bool checked() const;
void checkedChanges() const;
void checkedValue() const;
void setChecked(bool checked, NotifyAboutChange notify); void setChecked(bool checked, NotifyAboutChange notify);
void checkedChanged();
Checkbox *checkbox() { Checkbox *checkbox() {
return this; return this;
} }

View File

@ -305,11 +305,10 @@ void TermsBox::prepare() {
} }
if (age) { if (age) {
base::ObservableViewer( age->entity()->checkedChanges(
age->entity()->checkedChanged
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
toggleAgeError(false); toggleAgeError(false);
}, lifetime()); }, age->lifetime());
heightValue( heightValue(
) | rpl::start_with_next([=](int height) { ) | rpl::start_with_next([=](int height) {