From 311678af806027643199b0137aa42468d354db15 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 9 Feb 2020 02:22:39 +0300 Subject: [PATCH] Added ability to filter languages in dictionaries manager. --- .../boxes/dictionaries_manager.cpp | 94 +++++++++++++++++-- .../SourceFiles/boxes/dictionaries_manager.h | 2 + 2 files changed, 87 insertions(+), 9 deletions(-) diff --git a/Telegram/SourceFiles/boxes/dictionaries_manager.cpp b/Telegram/SourceFiles/boxes/dictionaries_manager.cpp index cd8957ce59..e5e99cbd3e 100644 --- a/Telegram/SourceFiles/boxes/dictionaries_manager.cpp +++ b/Telegram/SourceFiles/boxes/dictionaries_manager.cpp @@ -16,12 +16,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "mainwidget.h" #include "mtproto/dedicated_file_loader.h" +#include "spellcheck/spellcheck_utils.h" #include "styles/style_layers.h" #include "styles/style_settings.h" #include "styles/style_boxes.h" #include "ui/wrap/vertical_layout.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" +#include "ui/widgets/multi_select.h" #include "ui/widgets/popup_menu.h" #include "ui/wrap/slide_wrap.h" #include "ui/effects/animations.h" @@ -34,6 +36,13 @@ using namespace Storage::CloudBlob; using Loading = MTP::DedicatedLoader::Progress; using DictState = BlobState; +using QueryCallback = Fn; +constexpr auto kMaxQueryLength = 15; + +#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) +#define OLD_QT +using QStringView = QString; +#endif class Loader : public BlobLoader { public: @@ -58,11 +67,13 @@ public: Inner(QWidget *parent, Dictionaries enabledDictionaries); Dictionaries enabledRows() const; + QueryCallback queryCallback() const; private: void setupContent(Dictionaries enabledDictionaries); Dictionaries _enabledRows; + QueryCallback _queryCallback; }; @@ -115,12 +126,27 @@ void Loader::unpack(const QString &path) { void Loader::destroy() { } +auto CreateMultiSelect(QWidget *parent) { + const auto result = Ui::CreateChild( + parent, + st::contactsMultiSelect, + tr::lng_participant_filter()); + + result->resizeToWidth(st::boxWidth); + result->moveToLeft(0, 0); + return result; +} + Inner::Inner( QWidget *parent, Dictionaries enabledDictionaries) : RpWidget(parent) { setupContent(std::move(enabledDictionaries)); } +QueryCallback Inner::queryCallback() const { + return _queryCallback; +} + Dictionaries Inner::enabledRows() const { return _enabledRows; } @@ -128,11 +154,19 @@ Dictionaries Inner::enabledRows() const { auto AddButtonWithLoader( not_null content, const Spellchecker::Dict &dict, - bool buttonEnabled) { + bool buttonEnabled, + rpl::producer query) { const auto id = dict.id; buttonEnabled &= DictExists(id); - const auto button = content->add( + const auto locale = Spellchecker::LocaleFromLangId(id); + const std::vector indexList = { + dict.name, + QLocale::languageToString(locale.language()), + QLocale::countryToString(locale.country()) + }; + + const auto wrap = content->add( object_ptr>( content, object_ptr( @@ -141,8 +175,18 @@ auto AddButtonWithLoader( st::dictionariesSectionButton ) ) - )->entity(); + ); + const auto button = wrap->entity(); + std::move( + query + ) | rpl::start_with_next([=](auto string) { + wrap->toggle( + ranges::any_of(indexList, [&](const QString &s) { + return s.startsWith(string, Qt::CaseInsensitive); + }), + anim::type::instant); + }, button->lifetime()); const auto localLoader = button->lifetime() .make_state>(); @@ -283,12 +327,16 @@ auto AddButtonWithLoader( void Inner::setupContent(Dictionaries enabledDictionaries) { const auto content = Ui::CreateChild(this); + const auto queryStream = content->lifetime() + .make_state>(); + for (const auto &dict : Spellchecker::Dictionaries()) { const auto id = dict.id; const auto row = AddButtonWithLoader( content, dict, - ranges::contains(enabledDictionaries, id)); + ranges::contains(enabledDictionaries, id), + queryStream->events()); row->toggledValue( ) | rpl::start_with_next([=](auto enabled) { if (enabled) { @@ -300,6 +348,13 @@ void Inner::setupContent(Dictionaries enabledDictionaries) { }, row->lifetime()); } + _queryCallback = [=](const QString &query) { + if (query.size() >= kMaxQueryLength) { + return; + } + queryStream->fire_copy(query); + }; + content->resizeToWidth(st::boxWidth); Ui::ResizeFitChild(this, content); } @@ -312,10 +367,25 @@ ManageDictionariesBox::ManageDictionariesBox( : _session(session) { } +void ManageDictionariesBox::setInnerFocus() { + _setInnerFocus(); +} + void ManageDictionariesBox::prepare() { - const auto inner = setInnerWidget(object_ptr( - this, - _session->settings().dictionariesEnabled())); + const auto multiSelect = CreateMultiSelect(this); + + const auto inner = setInnerWidget( + object_ptr( + this, + _session->settings().dictionariesEnabled()), + st::boxScroll, + multiSelect->height() + ); + + multiSelect->setQueryChangedCallback(inner->queryCallback()); + _setInnerFocus = [=] { + multiSelect->setInnerFocus(); + }; // The initial list of enabled rows may differ from the list of languages // in settings, so we should store it when box opens @@ -342,10 +412,16 @@ void ManageDictionariesBox::prepare() { setDimensionsToContent(st::boxWidth, inner); - inner->heightValue( + using namespace rpl::mappers; + const auto max = lifetime().make_state(0); + rpl::combine( + inner->heightValue(), + multiSelect->heightValue(), + _1 + _2 ) | rpl::start_with_next([=](int height) { using std::min; - setDimensions(st::boxWidth, min(height, st::boxMaxListHeight)); + accumulate_max(*max, height); + setDimensions(st::boxWidth, min(*max, st::boxMaxListHeight), true); }, inner->lifetime()); } diff --git a/Telegram/SourceFiles/boxes/dictionaries_manager.h b/Telegram/SourceFiles/boxes/dictionaries_manager.h index f819e140dd..f137a76ca7 100644 --- a/Telegram/SourceFiles/boxes/dictionaries_manager.h +++ b/Telegram/SourceFiles/boxes/dictionaries_manager.h @@ -25,9 +25,11 @@ public: protected: void prepare() override; + void setInnerFocus() override; private: const not_null _session; + Fn _setInnerFocus; };