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 { class EditPrivacyBox::OptionWidget : public TWidget {
public: public:
OptionWidget(QWidget *parent, int value, bool selected, const QString &text, const QString &description); OptionWidget(QWidget *parent, const std::shared_ptr<Ui::RadiobuttonGroup> &group, int value, 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();
}
QMargins getMargins() const override { QMargins getMargins() const override {
return _option->getMargins(); 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) EditPrivacyBox::OptionWidget::OptionWidget(QWidget *parent, const std::shared_ptr<Ui::RadiobuttonGroup> &group, int value, const QString &text, const QString &description) : TWidget(parent)
, _option(this, qsl("privacy_option"), value, text, selected, st::defaultBoxCheckbox) , _option(this, group, value, text, st::defaultBoxCheckbox)
, _description(this, description, Ui::FlatLabel::InitType::Simple, st::editPrivacyLabel) { , _description(this, description, Ui::FlatLabel::InitType::Simple, st::editPrivacyLabel) {
} }
@ -185,15 +178,15 @@ int EditPrivacyBox::resizeGetHeight(int newWidth) {
int EditPrivacyBox::countDefaultHeight(int newWidth) { int EditPrivacyBox::countDefaultHeight(int newWidth) {
auto height = 0; 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); auto description = _controller->optionDescription(option);
if (description.isEmpty()) { if (description.isEmpty()) {
return 0; return 0;
} }
auto value = static_cast<int>(Option::Everyone); auto value = static_cast<int>(Option::Everyone);
auto selected = false; auto fake = object_ptr<OptionWidget>(nullptr, fakeGroup, value, label, description);
auto fake = object_ptr<OptionWidget>(nullptr, value, selected, label, description);
fake->resizeToNaturalWidth(newWidth - st::editPrivacyOptionMargin.left() - st::editPrivacyOptionMargin.right()); fake->resizeToNaturalWidth(newWidth - st::editPrivacyOptionMargin.left() - st::editPrivacyOptionMargin.right());
return st::editPrivacyOptionMargin.top() + fake->heightNoMargins() + st::editPrivacyOptionMargin.bottom(); 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); auto selected = (_option == option);
if (!description.isEmpty() || selected) { if (!description.isEmpty() || selected) {
auto value = static_cast<int>(option); auto value = static_cast<int>(option);
widget.create(this, value, selected, label, description); widget.create(this, _optionGroup, value, label, description);
widget->setChangedCallback([this, option, widget = widget.data()] {
if (widget->checked()) {
_option = option;
_alwaysLink->toggleAnimated(showExceptionLink(Exception::Always));
_neverLink->toggleAnimated(showExceptionLink(Exception::Never));
}
});
} }
} }
void EditPrivacyBox::createWidgets() { void EditPrivacyBox::createWidgets() {
_loading.destroy(); _loading.destroy();
_optionGroup = std::make_shared<Ui::RadiobuttonGroup>(static_cast<int>(_option));
createOption(Option::Everyone, _everyone, lang(lng_edit_privacy_everyone)); createOption(Option::Everyone, _everyone, lang(lng_edit_privacy_everyone));
createOption(Option::Contacts, _contacts, lang(lng_edit_privacy_contacts)); createOption(Option::Contacts, _contacts, lang(lng_edit_privacy_contacts));
createOption(Option::Nobody, _nobody, lang(lng_edit_privacy_nobody)); 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); _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); _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 { namespace Ui {
class FlatLabel; class FlatLabel;
class LinkButton; class LinkButton;
class RadiobuttonGroup;
template <typename Widget> template <typename Widget>
class WidgetSlideWrap; class WidgetSlideWrap;
} // namespace Ui } // namespace Ui
@ -103,6 +104,7 @@ private:
std::unique_ptr<Controller> _controller; std::unique_ptr<Controller> _controller;
Option _option = Option::Everyone; Option _option = Option::Everyone;
std::shared_ptr<Ui::RadiobuttonGroup> _optionGroup;
object_ptr<Ui::FlatLabel> _loading; object_ptr<Ui::FlatLabel> _loading;
object_ptr<OptionWidget> _everyone = { nullptr }; object_ptr<OptionWidget> _everyone = { nullptr };
object_ptr<OptionWidget> _contacts = { nullptr }; object_ptr<OptionWidget> _contacts = { nullptr };

View File

@ -37,13 +37,13 @@ void LanguageBox::prepare() {
auto haveTestLang = (cLang() == languageTest); auto haveTestLang = (cLang() == languageTest);
_langGroup = std::make_shared<Ui::RadiobuttonGroup>(cLang());
auto y = st::boxOptionListPadding.top(); auto y = st::boxOptionListPadding.top();
_langs.reserve(languageCount + (haveTestLang ? 1 : 0)); _langs.reserve(languageCount + (haveTestLang ? 1 : 0));
if (haveTestLang) { 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); _langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
y += _langs.back()->heightNoMargins() + st::boxOptionListSkip; y += _langs.back()->heightNoMargins() + st::boxOptionListSkip;
connect(_langs.back(), SIGNAL(changed()), this, SLOT(onChange()));
} }
for (auto i = 0; i != languageCount; ++i) { for (auto i = 0; i != languageCount; ++i) {
LangLoaderResult result; LangLoaderResult result;
@ -53,11 +53,11 @@ void LanguageBox::prepare() {
} else { } else {
result.insert(lng_language_name, langOriginal(lng_language_name)); 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); _langs.back()->move(st::boxPadding.left() + st::boxOptionListPadding.left(), y);
y += _langs.back()->heightNoMargins() + st::boxOptionListSkip; 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); 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()); 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() { void LanguageBox::languageChanged(int languageId) {
if (!isBoxShown()) return; Expects(languageId == languageTest || (languageId >= 0 && languageId < base::array_size(LanguageCodes)));
if (languageId == cLang()) {
return;
}
for (int32 i = 0, l = _langs.size(); i < l; ++i) {
int32 langId = _langs[i]->val();
if (_langs[i]->checked() && langId != cLang()) {
LangLoaderResult result; LangLoaderResult result;
if (langId > 0) { if (languageId > 0) {
LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[langId].c_str() + qsl(".strings"), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok)); LangLoaderPlain loader(qsl(":/langs/lang_") + LanguageCodes[languageId].c_str() + qsl(".strings"), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
result = loader.found(); result = loader.found();
} else if (langId == languageTest) { } else if (languageId == languageTest) {
LangLoaderPlain loader(cLangFile(), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok)); LangLoaderPlain loader(cLangFile(), langLoaderRequest(lng_sure_save_language, lng_cancel, lng_box_ok));
result = loader.found(); result = loader.found();
} }
auto text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)), auto text = result.value(lng_sure_save_language, langOriginal(lng_sure_save_language)),
save = result.value(lng_box_ok, langOriginal(lng_box_ok)), save = result.value(lng_box_ok, langOriginal(lng_box_ok)),
cancel = result.value(lng_cancel, langOriginal(lng_cancel)); cancel = result.value(lng_cancel, langOriginal(lng_cancel));
Ui::show(Box<ConfirmBox>(text, save, cancel, base::lambda_guarded(this, [this] { Ui::show(Box<ConfirmBox>(text, save, cancel, base::lambda_guarded(this, [this, languageId] {
saveLanguage(); cSetLang(languageId);
}), base::lambda_guarded(this, [this] {
restoreLanguage();
})), KeepOtherLayers);
}
}
}
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(); Local::writeSettings();
App::restart(); 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" #include "boxes/abstractbox.h"
namespace Ui { namespace Ui {
class RadiobuttonGroup;
class Radiobutton; class Radiobutton;
} // namespace Ui } // namespace Ui
@ -38,13 +39,10 @@ protected:
void mousePressEvent(QMouseEvent *e) override; void mousePressEvent(QMouseEvent *e) override;
private slots:
void onChange();
private: private:
void saveLanguage(); void languageChanged(int languageId);
void restoreLanguage();
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" #include "mainwindow.h"
ReportBox::ReportBox(QWidget*, PeerData *peer) : _peer(peer) ReportBox::ReportBox(QWidget*, PeerData *peer) : _peer(peer)
, _reasonSpam(this, qsl("report_reason"), ReasonSpam, lang(lng_report_reason_spam), true, st::defaultBoxCheckbox) , _reasonGroup(std::make_shared<Ui::RadiobuttonGroup>(ReasonSpam))
, _reasonViolence(this, qsl("report_reason"), ReasonViolence, lang(lng_report_reason_violence), false, st::defaultBoxCheckbox) , _reasonSpam(this, _reasonGroup, ReasonSpam, lang(lng_report_reason_spam), st::defaultBoxCheckbox)
, _reasonPornography(this, qsl("report_reason"), ReasonPornography, lang(lng_report_reason_pornography), false, st::defaultBoxCheckbox) , _reasonViolence(this, _reasonGroup, ReasonViolence, lang(lng_report_reason_violence), st::defaultBoxCheckbox)
, _reasonOther(this, qsl("report_reason"), ReasonOther, lang(lng_report_reason_other), false, 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() { void ReportBox::prepare() {
@ -42,10 +43,7 @@ void ReportBox::prepare() {
addButton(lang(lng_report_button), [this] { onReport(); }); addButton(lang(lng_report_button), [this] { onReport(); });
addButton(lang(lng_cancel), [this] { closeBox(); }); addButton(lang(lng_cancel), [this] { closeBox(); });
connect(_reasonSpam, SIGNAL(changed()), this, SLOT(onChange())); _reasonGroup->setChangedCallback([this](int value) { reasonChanged(value); });
connect(_reasonViolence, SIGNAL(changed()), this, SLOT(onChange()));
connect(_reasonPornography, SIGNAL(changed()), this, SLOT(onChange()));
connect(_reasonOther, SIGNAL(changed()), this, SLOT(onChange()));
updateMaxHeight(); updateMaxHeight();
} }
@ -63,8 +61,8 @@ void ReportBox::resizeEvent(QResizeEvent *e) {
} }
} }
void ReportBox::onChange() { void ReportBox::reasonChanged(int reason) {
if (_reasonOther->checked()) { if (reason == ReasonOther) {
if (!_reasonOtherText) { if (!_reasonOtherText) {
_reasonOtherText.create(this, st::profileReportReasonOther, lang(lng_report_reason_description)); _reasonOtherText.create(this, st::profileReportReasonOther, lang(lng_report_reason_description));
_reasonOtherText->show(); _reasonOtherText->show();
@ -106,15 +104,13 @@ void ReportBox::onReport() {
} }
auto getReason = [this]() { auto getReason = [this]() {
if (_reasonViolence->checked()) { switch (_reasonGroup->value()) {
return MTP_inputReportReasonViolence(); case ReasonSpam: return MTP_inputReportReasonSpam();
} else if (_reasonPornography->checked()) { case ReasonViolence: return MTP_inputReportReasonViolence();
return MTP_inputReportReasonPornography(); case ReasonPornography: return MTP_inputReportReasonPornography();
} else if (_reasonOtherText) { case ReasonOther: return MTP_inputReportReasonOther(MTP_string(_reasonOtherText->getLastText()));
return MTP_inputReportReasonOther(MTP_string(_reasonOtherText->getLastText()));
} else {
return MTP_inputReportReasonSpam();
} }
Unexpected("Bad reason group value.");
}; };
_requestId = MTP::send(MTPaccount_ReportPeer(_peer->input, getReason()), rpcDone(&ReportBox::reportDone), rpcFail(&ReportBox::reportFail)); _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" #include "boxes/abstractbox.h"
namespace Ui { namespace Ui {
class RadiobuttonGroup;
class Radiobutton; class Radiobutton;
class InputArea; class InputArea;
} // namespace Ui } // namespace Ui
@ -35,7 +36,6 @@ public:
private slots: private slots:
void onReport(); void onReport();
void onChange();
void onDescriptionResized(); void onDescriptionResized();
void onClose() { void onClose() {
closeBox(); closeBox();
@ -48,6 +48,7 @@ protected:
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
private: private:
void reasonChanged(int reason);
void updateMaxHeight(); void updateMaxHeight();
void reportDone(const MTPBool &result); void reportDone(const MTPBool &result);
@ -55,6 +56,7 @@ private:
PeerData *_peer; PeerData *_peer;
std::shared_ptr<Ui::RadiobuttonGroup> _reasonGroup;
object_ptr<Ui::Radiobutton> _reasonSpam; object_ptr<Ui::Radiobutton> _reasonSpam;
object_ptr<Ui::Radiobutton> _reasonViolence; object_ptr<Ui::Radiobutton> _reasonViolence;
object_ptr<Ui::Radiobutton> _reasonPornography; 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); 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) { 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, checked, st::defaultBoxCheckbox); child.create(this, group, value, text, st::defaultBoxCheckbox);
connect(child, SIGNAL(changed()), this, slot);
} }
void BlockWidget::createChildRow(object_ptr<Ui::LinkButton> &child, style::margins &margin, const QString &text, const char *slot, const style::LinkButton &st) { 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 { namespace Ui {
class Checkbox; class Checkbox;
class RadiobuttonGroup;
class Radiobutton; class Radiobutton;
class LinkButton; class LinkButton;
template <typename Widget> template <typename Widget>
@ -87,7 +88,7 @@ private:
margin.setBottom(margin.bottom() - padding.bottom()); 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::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 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); void addCreatedRow(TWidget *child, const style::margins &margin);

View File

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

View File

@ -98,12 +98,11 @@ private slots:
void onReplaceEmoji(); void onReplaceEmoji();
void onViewList(); void onViewList();
void onDontAskDownloadPath(); void onDontAskDownloadPath();
void onSendByEnter();
void onSendByCtrlEnter();
void onAutomaticMediaDownloadSettings(); void onAutomaticMediaDownloadSettings();
void onManageStickerSets(); void onManageStickerSets();
private: private:
void sendByChanged(int value);
void createControls(); void createControls();
object_ptr<Ui::Checkbox> _replaceEmoji = { nullptr }; 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 Ui {
namespace { 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 = { TextParseOptions _checkboxOptions = {
TextParseMultiline, // flags TextParseMultiline, // flags
0, // maxw 0, // maxw
@ -87,13 +35,6 @@ TextParseOptions _checkboxOptions = {
} // namespace } // 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) Checkbox::Checkbox(QWidget *parent, const QString &text, bool checked, const style::Checkbox &st) : RippleButton(parent, st.ripple)
, _st(st) , _st(st)
, _text(_st.style, text, _checkboxOptions) , _text(_st.style, text, _checkboxOptions)
@ -194,38 +135,41 @@ QPoint Checkbox::prepareRippleStartPosition() const {
return disabledRippleStartPosition(); 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) , _st(st)
, _text(_st.style, text, _checkboxOptions) , _text(_st.style, text, _checkboxOptions)
, _checked(checked) , _checked(_group->hasValue() && _group->value() == _value) {
, _group(radiobuttons.reg(group)) _group->registerButton(this);
, _value(value) {
if (_st.width <= 0) { if (_st.width <= 0) {
resizeToWidth(_text.maxWidth() - _st.width); resizeToWidth(_text.maxWidth() - _st.width);
} else { } else {
resizeToWidth(_st.width); resizeToWidth(_st.width);
} }
_checkRect = myrtlrect(_st.margin.left(), _st.margin.top(), _st.diameter, _st.diameter); _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 { void Radiobutton::handleNewGroupValue(int value) {
return _checked; auto checked = (value == _value);
}
void Radiobutton::setChecked(bool checked) {
if (_checked != checked) { if (_checked != checked) {
_checked = checked; _checked = checked;
_a_checked.start([this] { update(_checkRect); }, _checked ? 0. : 1., _checked ? 1. : 0., _st.duration); _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()); _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) { void Radiobutton::onStateChanged(State was, StateChangeSource source) {
RippleButton::onStateChanged(was, source); RippleButton::onStateChanged(was, source);
@ -292,6 +231,13 @@ void Radiobutton::onStateChanged(State was, StateChangeSource source) {
} else if (!isDisabled() && (was & StateFlag::Disabled)) { } else if (!isDisabled() && (was & StateFlag::Disabled)) {
setCursor(style::cur_pointer); 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) { int Radiobutton::resizeGetHeight(int newWidth) {
@ -310,25 +256,8 @@ QPoint Radiobutton::prepareRippleStartPosition() const {
return disabledRippleStartPosition(); 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() { Radiobutton::~Radiobutton() {
reinterpret_cast<RadiobuttonGroup*>(_group)->remove(this); _group->unregisterButton(this);
} }
} // namespace Ui } // namespace Ui

View File

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