|
| 1 | +/* |
| 2 | +This file is part of Telegram Desktop, |
| 3 | +the official desktop application for the Telegram messaging service. |
| 4 | +
|
| 5 | +For license and copyright information please follow this link: |
| 6 | +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL |
| 7 | +*/ |
| 8 | +#include "ui/widgets/passcode_strength_meter.h" |
| 9 | + |
| 10 | +#include "lang/lang_keys.h" |
| 11 | +#include "ui/widgets/labels.h" |
| 12 | +#include "ui/painter.h" |
| 13 | +#include "ui/qt_object_factory.h" |
| 14 | + |
| 15 | +#include "styles/style_passcode_strength_meter.h" |
| 16 | + |
| 17 | +namespace Ui { |
| 18 | +namespace { |
| 19 | + |
| 20 | +constexpr auto kSegmentCount = int(PasscodeStrengthBand::Strong) + 1; |
| 21 | + |
| 22 | +[[nodiscard]] rpl::producer<QString> AdviceText( |
| 23 | + PasscodeStrengthAdvice advice) { |
| 24 | + switch (advice) { |
| 25 | + case PasscodeStrengthAdvice::TooShort: |
| 26 | + return tr::lng_passcode_strength_advice_short(); |
| 27 | + case PasscodeStrengthAdvice::CommonWord: |
| 28 | + return tr::lng_passcode_strength_advice_word(); |
| 29 | + case PasscodeStrengthAdvice::LeetWord: |
| 30 | + return tr::lng_passcode_strength_advice_leet(); |
| 31 | + case PasscodeStrengthAdvice::Sequence: |
| 32 | + return tr::lng_passcode_strength_advice_sequence(); |
| 33 | + case PasscodeStrengthAdvice::Repeat: |
| 34 | + return tr::lng_passcode_strength_advice_repeat(); |
| 35 | + case PasscodeStrengthAdvice::Keyboard: |
| 36 | + return tr::lng_passcode_strength_advice_keyboard(); |
| 37 | + case PasscodeStrengthAdvice::DateLike: |
| 38 | + return tr::lng_passcode_strength_advice_date(); |
| 39 | + case PasscodeStrengthAdvice::AddVariety: |
| 40 | + return tr::lng_passcode_strength_advice_variety(); |
| 41 | + case PasscodeStrengthAdvice::Fine: |
| 42 | + return tr::lng_passcode_strength_advice_fine(); |
| 43 | + } |
| 44 | + Unexpected("Advice in AdviceText."); |
| 45 | +} |
| 46 | + |
| 47 | +[[nodiscard]] const style::color &BandColor( |
| 48 | + const style::PasscodeStrengthMeter &st, |
| 49 | + PasscodeStrengthBand band) { |
| 50 | + switch (band) { |
| 51 | + case PasscodeStrengthBand::VeryWeak: return st.veryWeakFg; |
| 52 | + case PasscodeStrengthBand::Weak: return st.weakFg; |
| 53 | + case PasscodeStrengthBand::Good: return st.goodFg; |
| 54 | + case PasscodeStrengthBand::Strong: return st.strongFg; |
| 55 | + } |
| 56 | + Unexpected("Band in BandColor."); |
| 57 | +} |
| 58 | + |
| 59 | +} // namespace |
| 60 | + |
| 61 | +PasscodeStrengthMeter::PasscodeStrengthMeter( |
| 62 | + QWidget *parent, |
| 63 | + const style::PasscodeStrengthMeter &st) |
| 64 | +: RpWidget(parent) |
| 65 | +, _st(st) |
| 66 | +, _label(CreateChild<FlatLabel>(this, _st.label)) { |
| 67 | + _label->heightValue() | rpl::on_next([=] { |
| 68 | + if (!_inResize) { |
| 69 | + resizeToWidth(width()); |
| 70 | + } |
| 71 | + }, lifetime()); |
| 72 | +} |
| 73 | + |
| 74 | +void PasscodeStrengthMeter::showCandidate(const QString &candidate) { |
| 75 | + _empty = candidate.isEmpty(); |
| 76 | + _strength = EstimatePasscodeStrength(candidate); |
| 77 | + _adviceLifetime.destroy(); |
| 78 | + if (_empty) { |
| 79 | + _label->setText(QString()); |
| 80 | + } else { |
| 81 | + AdviceText(_strength.advice) | rpl::on_next([=]( |
| 82 | + const QString &text) { |
| 83 | + _label->setText(text); |
| 84 | + }, _adviceLifetime); |
| 85 | + } |
| 86 | + update(); |
| 87 | +} |
| 88 | + |
| 89 | +int PasscodeStrengthMeter::resizeGetHeight(int newWidth) { |
| 90 | + _inResize = true; |
| 91 | + _label->resizeToWidth(newWidth); |
| 92 | + _label->moveToLeft(0, _st.height + _st.labelSkip, newWidth); |
| 93 | + _inResize = false; |
| 94 | + |
| 95 | + const auto labelHeight = std::max( |
| 96 | + _label->height(), |
| 97 | + _st.label.style.font->height); |
| 98 | + return _st.height + _st.labelSkip + labelHeight; |
| 99 | +} |
| 100 | + |
| 101 | +void PasscodeStrengthMeter::paintEvent(QPaintEvent *e) { |
| 102 | + auto p = QPainter(this); |
| 103 | + auto hq = PainterHighQualityEnabler(p); |
| 104 | + |
| 105 | + p.setPen(Qt::NoPen); |
| 106 | + |
| 107 | + const auto spacing = _st.segmentSpacing; |
| 108 | + const auto available = width() - spacing * (kSegmentCount - 1); |
| 109 | + const auto bandFg = _empty |
| 110 | + ? _st.emptyFg |
| 111 | + : BandColor(_st, _strength.band); |
| 112 | + const auto filled = _empty ? 0 : (int(_strength.band) + 1); |
| 113 | + auto left = 0; |
| 114 | + for (auto i = 0; i != kSegmentCount; ++i) { |
| 115 | + const auto segment = (available * (i + 1) / kSegmentCount) |
| 116 | + - (available * i / kSegmentCount); |
| 117 | + p.setBrush((i < filled) ? bandFg : _st.emptyFg); |
| 118 | + p.drawRoundedRect( |
| 119 | + QRect(left, 0, segment, _st.height), |
| 120 | + _st.segmentRadius, |
| 121 | + _st.segmentRadius); |
| 122 | + left += segment + spacing; |
| 123 | + } |
| 124 | +} |
| 125 | + |
| 126 | +rpl::producer<QString> PasscodeStrengthBandName(PasscodeStrengthBand band) { |
| 127 | + switch (band) { |
| 128 | + case PasscodeStrengthBand::VeryWeak: |
| 129 | + return tr::lng_passcode_strength_very_weak(); |
| 130 | + case PasscodeStrengthBand::Weak: |
| 131 | + return tr::lng_passcode_strength_weak(); |
| 132 | + case PasscodeStrengthBand::Good: |
| 133 | + return tr::lng_passcode_strength_good(); |
| 134 | + case PasscodeStrengthBand::Strong: |
| 135 | + return tr::lng_passcode_strength_strong(); |
| 136 | + } |
| 137 | + Unexpected("Band in PasscodeStrengthBandName."); |
| 138 | +} |
| 139 | + |
| 140 | +const style::color &PasscodeStrengthBandColor(PasscodeStrengthBand band) { |
| 141 | + return BandColor(st::defaultPasscodeStrengthMeter, band); |
| 142 | +} |
| 143 | + |
| 144 | +} // namespace Ui |
0 commit comments