mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-02-17 13:27:01 +00:00
WIP radiobuttons refactoring.
This commit is contained in:
parent
7546245213
commit
0a40bf2071
@ -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);
|
||||
|
@ -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 };
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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() {
|
||||
|
@ -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 };
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user