WIP radiobuttons refactoring.

This commit is contained in:
John Preston 2017-03-18 14:55:04 +03:00
parent 7546245213
commit 0a40bf2071
12 changed files with 158 additions and 231 deletions

View File

@ -90,14 +90,7 @@ std::unique_ptr<PrivacyExceptionsBoxController::Row> PrivacyExceptionsBoxControl
class EditPrivacyBox::OptionWidget : public TWidget {
public:
OptionWidget(QWidget *parent, int value, bool selected, const QString &text, const QString &description);
void setChangedCallback(base::lambda<void()> callback) {
connect(_option, SIGNAL(changed()), base::lambda_slot(this, std::move(callback)), SLOT(action()));
}
bool checked() const {
return _option->checked();
}
OptionWidget(QWidget *parent, const std::shared_ptr<Ui::RadiobuttonGroup> &group, int value, const QString &text, const QString &description);
QMargins getMargins() const override {
return _option->getMargins();
@ -112,8 +105,8 @@ private:
};
EditPrivacyBox::OptionWidget::OptionWidget(QWidget *parent, int value, bool selected, const QString &text, const QString &description) : TWidget(parent)
, _option(this, qsl("privacy_option"), value, text, selected, st::defaultBoxCheckbox)
EditPrivacyBox::OptionWidget::OptionWidget(QWidget *parent, const std::shared_ptr<Ui::RadiobuttonGroup> &group, int value, const QString &text, const QString &description) : TWidget(parent)
, _option(this, group, value, text, st::defaultBoxCheckbox)
, _description(this, description, Ui::FlatLabel::InitType::Simple, st::editPrivacyLabel) {
}
@ -185,15 +178,15 @@ int EditPrivacyBox::resizeGetHeight(int newWidth) {
int EditPrivacyBox::countDefaultHeight(int newWidth) {
auto height = 0;
auto optionHeight = [this, newWidth](Option option, const QString &label) {
auto fakeGroup = std::make_shared<Ui::RadiobuttonGroup>(0);
auto optionHeight = [this, newWidth, &fakeGroup](Option option, const QString &label) {
auto description = _controller->optionDescription(option);
if (description.isEmpty()) {
return 0;
}
auto value = static_cast<int>(Option::Everyone);
auto selected = false;
auto fake = object_ptr<OptionWidget>(nullptr, value, selected, label, description);
auto fake = object_ptr<OptionWidget>(nullptr, fakeGroup, value, label, description);
fake->resizeToNaturalWidth(newWidth - st::editPrivacyOptionMargin.left() - st::editPrivacyOptionMargin.right());
return st::editPrivacyOptionMargin.top() + fake->heightNoMargins() + st::editPrivacyOptionMargin.bottom();
};
@ -304,23 +297,23 @@ void EditPrivacyBox::createOption(Option option, object_ptr<OptionWidget> &widge
auto selected = (_option == option);
if (!description.isEmpty() || selected) {
auto value = static_cast<int>(option);
widget.create(this, value, selected, label, description);
widget->setChangedCallback([this, option, widget = widget.data()] {
if (widget->checked()) {
_option = option;
_alwaysLink->toggleAnimated(showExceptionLink(Exception::Always));
_neverLink->toggleAnimated(showExceptionLink(Exception::Never));
}
});
widget.create(this, _optionGroup, value, label, description);
}
}
void EditPrivacyBox::createWidgets() {
_loading.destroy();
_optionGroup = std::make_shared<Ui::RadiobuttonGroup>(static_cast<int>(_option));
createOption(Option::Everyone, _everyone, lang(lng_edit_privacy_everyone));
createOption(Option::Contacts, _contacts, lang(lng_edit_privacy_contacts));
createOption(Option::Nobody, _nobody, lang(lng_edit_privacy_nobody));
_optionGroup->setChangedCallback([this](int value) {
_option = static_cast<Option>(value);
_alwaysLink->toggleAnimated(showExceptionLink(Exception::Always));
_neverLink->toggleAnimated(showExceptionLink(Exception::Never));
});
_description.create(this, _controller->description(), Ui::FlatLabel::InitType::Simple, st::editPrivacyLabel);
_exceptionsTitle.create(this, lang(lng_edit_privacy_exceptions), Ui::FlatLabel::InitType::Simple, st::editPrivacyTitle);

View File

@ -25,6 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Ui {
class FlatLabel;
class LinkButton;
class RadiobuttonGroup;
template <typename Widget>
class WidgetSlideWrap;
} // namespace Ui
@ -103,6 +104,7 @@ private:
std::unique_ptr<Controller> _controller;
Option _option = Option::Everyone;
std::shared_ptr<Ui::RadiobuttonGroup> _optionGroup;
object_ptr<Ui::FlatLabel> _loading;
object_ptr<OptionWidget> _everyone = { nullptr };
object_ptr<OptionWidget> _contacts = { nullptr };

View File

@ -37,13 +37,13 @@ void LanguageBox::prepare() {
auto haveTestLang = (cLang() == languageTest);
_langGroup = std::make_shared<Ui::RadiobuttonGroup>(cLang());
auto y = st::boxOptionListPadding.top();
_langs.reserve(languageCount + (haveTestLang ? 1 : 0));
if (haveTestLang) {
_langs.push_back(new Ui::Radiobutton(this, qsl("lang"), languageTest, qsl("Custom Lang"), (cLang() == languageTest), st::langsButton));
_langs.emplace_back(this, _langGroup, languageTest, qsl("Custom Lang"), st::langsButton);
_langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
y += _langs.back()->heightNoMargins() + st::boxOptionListSkip;
connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange()));
}
for (auto i = 0; i != languageCount; ++i) {
LangLoaderResult result;
@ -53,11 +53,11 @@ void LanguageBox::prepare() {
} else {
result.insert(lng_language_name, langOriginal(lng_language_name));
}
_langs.push_back(new Ui::Radiobutton(this, qsl("lang"), i, result.value(lng_language_name, LanguageCodes[i].c_str() + qsl(" language")), (cLang() == i), st::langsButton));
_langs.emplace_back(this, _langGroup, i, result.value(lng_language_name, LanguageCodes[i].c_str() + qsl(" language")), st::langsButton);
_langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
y += _langs.back()->heightNoMargins() + st::boxOptionListSkip;
connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange()));
}
_langGroup->setChangedCallback([this](int value) { languageChanged(value); });
auto optionsCount = languageCount + (haveTestLang ? 1 : 0);
setDimensions(st::langsWidth, st::boxOptionListPadding.top() + optionsCount * st::langsButton.height + (optionsCount - 1) * st::boxOptionListSkip + st::boxOptionListPadding.bottom() + st::boxPadding.bottom());
@ -81,46 +81,29 @@ void LanguageBox::mousePressEvent(QMouseEvent *e) {
}
}
void LanguageBox::onChange() {
if (!isBoxShown()) return;
void LanguageBox::languageChanged(int languageId) {
Expects(languageId == languageTest || (languageId >= 0 && languageId < base::array_size(LanguageCodes)));
for (int32 i = 0, l = _langs.size(); i < l; ++i) {
int32 langId = _langs[i]->val();
if (_langs[i]->checked() && langId != cLang()) {
LangLoaderResult result;
if (langId > 0) {
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[langId].c_str() + qsl(".strings"), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
result = loader.found();
} else if (langId == languageTest) {
LangLoaderPlain loader(cLangFile(), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
result = loader.found();
}
auto text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)),
save = result.value(lng_box_ok, langOriginal(lng_box_ok)),
cancel = result.value(lng_cancel, langOriginal(lng_cancel));
Ui::show(Box<ConfirmBox>(text, save, cancel, base::lambda_guarded(this, [this] {
saveLanguage();
}), base::lambda_guarded(this, [this] {
restoreLanguage();
})), KeepOtherLayers);
}
if (languageId == cLang()) {
return;
}
}
void LanguageBox::restoreLanguage() {
for (auto i = 0, l = _langs.size(); i != l; ++i) {
if (_langs[i]->val() == cLang()) {
_langs[i]->setChecked(true);
}
}
}
void LanguageBox::saveLanguage() {
for (auto i = 0, l = _langs.size(); i != l; ++i) {
if (_langs[i]->checked()) {
cSetLang(_langs[i]->val());
Local::writeSettings();
App::restart();
}
LangLoaderResult result;
if (languageId > 0) {
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[languageId].c_str() + qsl(".strings"), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
result = loader.found();
} else if (languageId == languageTest) {
LangLoaderPlain loader(cLangFile(), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
result = loader.found();
}
auto text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)),
save = result.value(lng_box_ok, langOriginal(lng_box_ok)),
cancel = result.value(lng_cancel, langOriginal(lng_cancel));
Ui::show(Box<ConfirmBox>(text, save, cancel, base::lambda_guarded(this, [this, languageId] {
cSetLang(languageId);
Local::writeSettings();
App::restart();
}), base::lambda_guarded(this, [this] {
_langGroup->setValue(cLang());
})), KeepOtherLayers);
}

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "boxes/abstractbox.h"
namespace Ui {
class RadiobuttonGroup;
class Radiobutton;
} // namespace Ui
@ -38,13 +39,10 @@ protected:
void mousePressEvent(QMouseEvent *e) override;
private slots:
void onChange();
private:
void saveLanguage();
void restoreLanguage();
void languageChanged(int languageId);
QVector<Ui::Radiobutton*> _langs;
std::shared_ptr<Ui::RadiobuttonGroup> _langGroup;
std::vector<object_ptr<Ui::Radiobutton>> _langs;
};

View File

@ -30,10 +30,11 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "mainwindow.h"
ReportBox::ReportBox(QWidget*, PeerData *peer) : _peer(peer)
, _reasonSpam(this, qsl("report_reason"), ReasonSpam, lang(lng_report_reason_spam), true, st::defaultBoxCheckbox)
, _reasonViolence(this, qsl("report_reason"), ReasonViolence, lang(lng_report_reason_violence), false, st::defaultBoxCheckbox)
, _reasonPornography(this, qsl("report_reason"), ReasonPornography, lang(lng_report_reason_pornography), false, st::defaultBoxCheckbox)
, _reasonOther(this, qsl("report_reason"), ReasonOther, lang(lng_report_reason_other), false, st::defaultBoxCheckbox) {
, _reasonGroup(std::make_shared<Ui::RadiobuttonGroup>(ReasonSpam))
, _reasonSpam(this, _reasonGroup, ReasonSpam, lang(lng_report_reason_spam), st::defaultBoxCheckbox)
, _reasonViolence(this, _reasonGroup, ReasonViolence, lang(lng_report_reason_violence), st::defaultBoxCheckbox)
, _reasonPornography(this, _reasonGroup, ReasonPornography, lang(lng_report_reason_pornography), st::defaultBoxCheckbox)
, _reasonOther(this, _reasonGroup, ReasonOther, lang(lng_report_reason_other), st::defaultBoxCheckbox) {
}
void ReportBox::prepare() {
@ -42,10 +43,7 @@ void ReportBox::prepare() {
addButton(lang(lng_report_button), [this] { onReport(); });
addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_reasonSpam, SIGNAL(changed()), this, SLOT(onChange()));
connect(_reasonViolence, SIGNAL(changed()), this, SLOT(onChange()));
connect(_reasonPornography, SIGNAL(changed()), this, SLOT(onChange()));
connect(_reasonOther, SIGNAL(changed()), this, SLOT(onChange()));
_reasonGroup->setChangedCallback([this](int value) { reasonChanged(value); });
updateMaxHeight();
}
@ -63,8 +61,8 @@ void ReportBox::resizeEvent(QResizeEvent *e) {
}
}
void ReportBox::onChange() {
if (_reasonOther->checked()) {
void ReportBox::reasonChanged(int reason) {
if (reason == ReasonOther) {
if (!_reasonOtherText) {
_reasonOtherText.create(this, st::profileReportReasonOther, lang(lng_report_reason_description));
_reasonOtherText->show();
@ -106,15 +104,13 @@ void ReportBox::onReport() {
}
auto getReason = [this]() {
if (_reasonViolence->checked()) {
return MTP_inputReportReasonViolence();
} else if (_reasonPornography->checked()) {
return MTP_inputReportReasonPornography();
} else if (_reasonOtherText) {
return MTP_inputReportReasonOther(MTP_string(_reasonOtherText->getLastText()));
} else {
return MTP_inputReportReasonSpam();
switch (_reasonGroup->value()) {
case ReasonSpam: return MTP_inputReportReasonSpam();
case ReasonViolence: return MTP_inputReportReasonViolence();
case ReasonPornography: return MTP_inputReportReasonPornography();
case ReasonOther: return MTP_inputReportReasonOther(MTP_string(_reasonOtherText->getLastText()));
}
Unexpected("Bad reason group value.");
};
_requestId = MTP::send(MTPaccount_ReportPeer(_peer->input, getReason()), rpcDone(&ReportBox::reportDone), rpcFail(&ReportBox::reportFail));
}

View File

@ -23,6 +23,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "boxes/abstractbox.h"
namespace Ui {
class RadiobuttonGroup;
class Radiobutton;
class InputArea;
} // namespace Ui
@ -35,7 +36,6 @@ public:
private slots:
void onReport();
void onChange();
void onDescriptionResized();
void onClose() {
closeBox();
@ -48,6 +48,7 @@ protected:
void resizeEvent(QResizeEvent *e) override;
private:
void reasonChanged(int reason);
void updateMaxHeight();
void reportDone(const MTPBool &result);
@ -55,6 +56,7 @@ private:
PeerData *_peer;
std::shared_ptr<Ui::RadiobuttonGroup> _reasonGroup;
object_ptr<Ui::Radiobutton> _reasonSpam;
object_ptr<Ui::Radiobutton> _reasonViolence;
object_ptr<Ui::Radiobutton> _reasonPornography;

View File

@ -90,9 +90,8 @@ void BlockWidget::createChildRow(object_ptr<Ui::Checkbox> &child, style::margins
connect(child, SIGNAL(changed()), this, slot);
}
void BlockWidget::createChildRow(object_ptr<Ui::Radiobutton> &child, style::margins &margin, const QString &group, int value, const QString &text, const char *slot, bool checked) {
child .create(this, group, value, text, checked, st::defaultBoxCheckbox);
connect(child, SIGNAL(changed()), this, slot);
void BlockWidget::createChildRow(object_ptr<Ui::Radiobutton> &child, style::margins &margin, const std::shared_ptr<Ui::RadiobuttonGroup> &group, int value, const QString &text) {
child.create(this, group, value, text, st::defaultBoxCheckbox);
}
void BlockWidget::createChildRow(object_ptr<Ui::LinkButton> &child, style::margins &margin, const QString &text, const char *slot, const style::LinkButton &st) {

View File

@ -25,6 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Ui {
class Checkbox;
class RadiobuttonGroup;
class Radiobutton;
class LinkButton;
template <typename Widget>
@ -87,7 +88,7 @@ private:
margin.setBottom(margin.bottom() - padding.bottom());
}
void createChildRow(object_ptr<Ui::Checkbox> &child, style::margins &margin, const QString &text, const char *slot, bool checked);
void createChildRow(object_ptr<Ui::Radiobutton> &child, style::margins &margin, const QString &group, int value, const QString &text, const char *slot, bool checked);
void createChildRow(object_ptr<Ui::Radiobutton> &child, style::margins &margin, const Ui::RadiobuttonGroup &group, int value, const QString &text);
void createChildRow(object_ptr<Ui::LinkButton> &child, style::margins &margin, const QString &text, const char *slot, const style::LinkButton &st = st::boxLinkButton);
void addCreatedRow(TWidget *child, const style::margins &margin);

View File

@ -180,8 +180,13 @@ void ChatSettingsWidget::createControls() {
}
#endif // OS_WIN_STORE
addChildRow(_sendByEnter, marginSmall, qsl("send_key"), 0, lang(lng_settings_send_enter), SLOT(onSendByEnter()), !cCtrlEnter());
addChildRow(_sendByCtrlEnter, marginSkip, qsl("send_key"), 1, lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_settings_send_cmdenter : lng_settings_send_ctrlenter), SLOT(onSendByCtrlEnter()), cCtrlEnter());
auto group = std::make_shared<Ui::RadiobuttonGroup>(cCtrlEnter() ? 1 : 0);
addChildRow(_sendByEnter, marginSmall, group, 0, lang(lng_settings_send_enter));
addChildRow(_sendByCtrlEnter, marginSkip, group, 1, lang((cPlatform() == dbipMac || cPlatform() == dbipMacOld) ? lng_settings_send_cmdenter : lng_settings_send_ctrlenter), SLOT(onSendByCtrlEnter()), cCtrlEnter());
group->setChangedCallback([this](int value) {
sendByChanged(value);
});
addChildRow(_automaticMediaDownloadSettings, marginSmall, lang(lng_media_auto_settings), SLOT(onAutomaticMediaDownloadSettings()));
addChildRow(_manageStickerSets, marginSmall, lang(lng_stickers_you_have), SLOT(onManageStickerSets()));
}
@ -205,20 +210,10 @@ void ChatSettingsWidget::onDontAskDownloadPath() {
#endif // OS_WIN_STORE
}
void ChatSettingsWidget::onSendByEnter() {
if (_sendByEnter->checked()) {
cSetCtrlEnter(false);
if (App::main()) App::main()->ctrlEnterSubmitUpdated();
Local::writeUserSettings();
}
}
void ChatSettingsWidget::onSendByCtrlEnter() {
if (_sendByCtrlEnter->checked()) {
cSetCtrlEnter(true);
if (App::main()) App::main()->ctrlEnterSubmitUpdated();
Local::writeUserSettings();
}
void ChatSettingsWidget::sendByChanged(int value) {
cSetCtrlEnter(value == 1);
if (App::main()) App::main()->ctrlEnterSubmitUpdated();
Local::writeUserSettings();
}
void ChatSettingsWidget::onAutomaticMediaDownloadSettings() {

View File

@ -98,12 +98,11 @@ private slots:
void onReplaceEmoji();
void onViewList();
void onDontAskDownloadPath();
void onSendByEnter();
void onSendByCtrlEnter();
void onAutomaticMediaDownloadSettings();
void onManageStickerSets();
private:
void sendByChanged(int value);
void createControls();
object_ptr<Ui::Checkbox> _replaceEmoji = { nullptr };

View File

@ -26,58 +26,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
namespace Ui {
namespace {
class RadiobuttonGroup : public QMap<Radiobutton*, bool> {
using Parent = QMap<Radiobutton*, bool>;
public:
RadiobuttonGroup(const QString &name) : _name(name) {
}
void remove(Radiobutton * const &radio);
int32 val() const {
return _val;
}
void setVal(int32 val) {
_val = val;
}
private:
QString _name;
int _val = 0;
};
class Radiobuttons : public QMap<QString, RadiobuttonGroup*> {
using Parent = QMap<QString, RadiobuttonGroup*>;
public:
RadiobuttonGroup *reg(const QString &group) {
typename Parent::const_iterator i = Parent::constFind(group);
if (i == Parent::cend()) {
i = Parent::insert(group, new RadiobuttonGroup(group));
}
return i.value();
}
int remove(const QString &group) {
typename Parent::iterator i = Parent::find(group);
if (i != Parent::cend()) {
delete i.value();
Parent::erase(i);
return 1;
}
return 0;
}
~Radiobuttons() {
for (typename Parent::const_iterator i = Parent::cbegin(), e = Parent::cend(); i != e; ++i) {
delete *i;
}
}
};
Radiobuttons radiobuttons;
TextParseOptions _checkboxOptions = {
TextParseMultiline, // flags
0, // maxw
@ -87,13 +35,6 @@ TextParseOptions _checkboxOptions = {
} // namespace
void RadiobuttonGroup::remove(Radiobutton * const &radio) {
Parent::remove(radio);
if (isEmpty()) {
radiobuttons.remove(_name);
}
}
Checkbox::Checkbox(QWidget *parent, const QString &text, bool checked, const style::Checkbox &st) : RippleButton(parent, st.ripple)
, _st(st)
, _text(_st.style, text, _checkboxOptions)
@ -194,38 +135,41 @@ QPoint Checkbox::prepareRippleStartPosition() const {
return disabledRippleStartPosition();
}
Radiobutton::Radiobutton(QWidget *parent, const QString &group, int32 value, const QString &text, bool checked, const style::Checkbox &st) : RippleButton(parent, st.ripple)
void RadiobuttonGroup::setValue(int value) {
if (_hasValue && _value == value) {
return;
}
_hasValue = true;
_value = value;
for (auto button : _buttons) {
button->handleNewGroupValue(_value);
}
if (_changedCallback) {
_changedCallback(_value);
}
}
Radiobutton::Radiobutton(QWidget *parent, const std::shared_ptr<RadiobuttonGroup> &group, int value, const QString &text, const style::Checkbox &st) : RippleButton(parent, st.ripple)
, _group(group)
, _value(value)
, _st(st)
, _text(_st.style, text, _checkboxOptions)
, _checked(checked)
, _group(radiobuttons.reg(group))
, _value(value) {
, _checked(_group->hasValue() && _group->value() == _value) {
_group->registerButton(this);
if (_st.width <= 0) {
resizeToWidth(_text.maxWidth() - _st.width);
} else {
resizeToWidth(_st.width);
}
_checkRect = myrtlrect(_st.margin.left(), _st.margin.top(), _st.diameter, _st.diameter);
connect(this, SIGNAL(clicked()), this, SLOT(onClicked()));
setCursor(style::cur_pointer);
reinterpret_cast<RadiobuttonGroup*>(_group)->insert(this, true);
if (_checked) onChanged();
}
bool Radiobutton::checked() const {
return _checked;
}
void Radiobutton::setChecked(bool checked) {
void Radiobutton::handleNewGroupValue(int value) {
auto checked = (value == _value);
if (_checked != checked) {
_checked = checked;
_a_checked.start([this] { update(_checkRect); }, _checked ? 0. : 1., _checked ? 1. : 0., _st.duration);
onChanged();
emit changed();
}
}
@ -279,11 +223,6 @@ void Radiobutton::paintEvent(QPaintEvent *e) {
_text.drawLeftElided(p, _st.margin.left() + _st.textPosition.x(), _st.margin.top() + _st.textPosition.y(), textWidth, width());
}
void Radiobutton::onClicked() {
if (isDisabled()) return;
setChecked(!checked());
}
void Radiobutton::onStateChanged(State was, StateChangeSource source) {
RippleButton::onStateChanged(was, source);
@ -292,6 +231,13 @@ void Radiobutton::onStateChanged(State was, StateChangeSource source) {
} else if (!isDisabled() && (was & StateFlag::Disabled)) {
setCursor(style::cur_pointer);
}
auto now = state();
if (!isDisabled() && (was & StateFlag::Over) && (now & StateFlag::Over)) {
if ((was & StateFlag::Down) && !(now & StateFlag::Down)) {
_group->setValue(_value);
}
}
}
int Radiobutton::resizeGetHeight(int newWidth) {
@ -310,25 +256,8 @@ QPoint Radiobutton::prepareRippleStartPosition() const {
return disabledRippleStartPosition();
}
void Radiobutton::onChanged() {
RadiobuttonGroup *group = reinterpret_cast<RadiobuttonGroup*>(_group);
if (checked()) {
int32 uncheck = group->val();
if (uncheck != _value) {
group->setVal(_value);
for (RadiobuttonGroup::const_iterator i = group->cbegin(), e = group->cend(); i != e; ++i) {
if (i.key()->val() == uncheck) {
i.key()->setChecked(false);
}
}
}
} else if (group->val() == _value) {
setChecked(true);
}
}
Radiobutton::~Radiobutton() {
reinterpret_cast<RadiobuttonGroup*>(_group)->remove(this);
_group->unregisterButton(this);
}
} // namespace Ui

View File

@ -71,19 +71,54 @@ private:
};
class Radiobutton : public RippleButton {
Q_OBJECT
class Radiobutton;
class RadiobuttonGroup {
public:
Radiobutton(QWidget *parent, const QString &group, int value, const QString &text, bool checked = false, const style::Checkbox &st = st::defaultCheckbox);
bool checked() const;
void setChecked(bool checked);
int val() const {
return _value;
RadiobuttonGroup() = default;
RadiobuttonGroup(int value) : _value(value), _hasValue(true) {
}
void setChangedCallback(base::lambda<void(int value)> callback) {
_changedCallback = std::move(callback);
}
bool hasValue() const {
return _hasValue;
}
int value() const {
return _value;
}
void setValue(int value);
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());
}
private:
friend class Radiobutton;
void registerButton(Radiobutton *button);
void unregisterButton(Radiobutton *button);
int _value = 0;
bool _hasValue = false;
base::lambda<void(int value)> _changedCallback;
std::vector<Radiobutton*> _buttons;
};
class Radiobutton : public RippleButton {
public:
Radiobutton(QWidget *parent, const std::shared_ptr<RadiobuttonGroup> &group, int value, const QString &text, const style::Checkbox &st = st::defaultCheckbox);
RadiobuttonGroup *group() const {
return _group.get();
}
QMargins getMargins() const override {
return _st.margin;
}
@ -100,26 +135,21 @@ protected:
QImage prepareRippleMask() const override;
QPoint prepareRippleStartPosition() const override;
public slots:
void onClicked();
signals:
void changed();
private:
void onChanged();
friend class RadiobuttonGroup;
void handleNewGroupValue(int value);
std::shared_ptr<RadiobuttonGroup> _group;
int _value = 0;
const style::Checkbox &_st;
Text _text;
QRect _checkRect;
bool _checked;
bool _checked = false;
Animation _a_checked;
void *_group;
int _value;
};
} // namespace Ui