diff --git a/resources/qss/settings.qss b/resources/qss/settings.qss index 54f1b599b..32d571924 100644 --- a/resources/qss/settings.qss +++ b/resources/qss/settings.qss @@ -34,12 +34,7 @@ chatterino--TitleLabel { font-family: "Segoe UI light"; font-size: 24px; color: #4FC3F7; -} - -chatterino--TitleLabel2 { - font-family: "Segoe UI light"; - font-size: 24px; - color: #bbb; + margin-top: 16px; } chatterino--DescriptionLabel { diff --git a/src/widgets/dialogs/SettingsDialog.cpp b/src/widgets/dialogs/SettingsDialog.cpp index 69536bede..2474ac26a 100644 --- a/src/widgets/dialogs/SettingsDialog.cpp +++ b/src/widgets/dialogs/SettingsDialog.cpp @@ -22,6 +22,7 @@ #include "widgets/settingspages/SpecialChannelsPage.hpp" #include +#include namespace chatterino { @@ -61,6 +62,19 @@ void SettingsDialog::initUi() // right side layout auto right = layoutCreator.emplace().withoutMargin(); { + auto title = right.emplace().withoutMargin(); + + auto edit = title.emplace().assign(&this->ui_.search); + QTimer::singleShot(100, edit.getElement(), + [edit = edit.getElement()]() { edit->setFocus(); }); + QObject::connect(edit.getElement(), &QLineEdit::textChanged, this, + [this](const QString &text) { + for (auto &&page : this->pages_) + { + page->filterElements(text); + } + }); + right.emplace() .assign(&this->ui_.pageStack) .withoutMargin(); @@ -104,26 +118,17 @@ void SettingsDialog::addTabs() this->addTab(new AccountsPage); - // this->ui_.tabContainer->addSpacing(16); - - // this->addTab(new LookPage); - // this->addTab(new FeelPage); - this->ui_.tabContainer->addSpacing(16); this->addTab(new CommandPage); - // this->addTab(new EmotesPage); this->addTab(new HighlightingPage); this->addTab(new IgnoresPage); this->ui_.tabContainer->addSpacing(16); this->addTab(new KeyboardSettingsPage); - // this->addTab(new LogsPage); this->addTab(this->ui_.moderationPage = new ModerationPage); this->addTab(new NotificationPage); - // this->addTab(new SpecialChannelsPage); - // this->addTab(new BrowserExtensionPage); this->addTab(new ExternalToolsPage); this->addTab(new AdvancedPage); @@ -140,6 +145,7 @@ void SettingsDialog::addTab(SettingsPage *page, Qt::Alignment alignment) this->ui_.pageStack->addWidget(page); this->ui_.tabContainer->addWidget(tab, 0, alignment); this->tabs_.push_back(tab); + this->pages_.push_back(page); if (this->tabs_.size() == 1) { diff --git a/src/widgets/dialogs/SettingsDialog.hpp b/src/widgets/dialogs/SettingsDialog.hpp index e5bc06595..e637fa280 100644 --- a/src/widgets/dialogs/SettingsDialog.hpp +++ b/src/widgets/dialogs/SettingsDialog.hpp @@ -8,6 +8,8 @@ #include #include +class QLineEdit; + namespace chatterino { class SettingsPage; @@ -54,8 +56,10 @@ private: QPushButton *okButton{}; QPushButton *cancelButton{}; ModerationPage *moderationPage{}; + QLineEdit *search{}; } ui_; std::vector tabs_; + std::vector pages_; SettingsDialogTab *selectedTab_{}; friend class SettingsDialogTab; diff --git a/src/widgets/settingspages/GeneralPage.cpp b/src/widgets/settingspages/GeneralPage.cpp index 6ee10777a..8081b2b93 100644 --- a/src/widgets/settingspages/GeneralPage.cpp +++ b/src/widgets/settingspages/GeneralPage.cpp @@ -36,20 +36,13 @@ TitleLabel *SettingsLayout::addTitle(const QString &title) { auto label = new TitleLabel(title + ":"); - if (this->count() != 0) - this->addSpacing(16); - + if (this->count() == 0) + label->setStyleSheet("margin-top: 0"); this->addWidget(label); - return label; -} -TitleLabel2 *SettingsLayout::addTitle2(const QString &title) -{ - auto label = new TitleLabel2(title + ":"); + // groups + this->groups_.push_back(Group{title, label, {}}); - this->addSpacing(16); - - this->addWidget(label); return label; } @@ -71,6 +64,10 @@ QCheckBox *SettingsLayout::addCheckbox(const QString &text, [&setting, inverse](bool state) { setting = inverse ^ state; }); this->addWidget(check); + + // groups + this->groups_.back().widgets.push_back({check, {text}}); + return check; } @@ -82,11 +79,17 @@ ComboBox *SettingsLayout::addDropdown(const QString &text, combo->setFocusPolicy(Qt::StrongFocus); combo->addItems(list); - layout->addWidget(new QLabel(text + ":")); + auto label = new QLabel(text + ":"); + layout->addWidget(label); layout->addStretch(1); layout->addWidget(combo); this->addLayout(layout); + + // groups + this->groups_.back().widgets.push_back({combo, {text}}); + this->groups_.back().widgets.push_back({label, {text}}); + return combo; } @@ -124,6 +127,9 @@ DescriptionLabel *SettingsLayout::addDescription(const QString &text) this->addWidget(label); + // groups + this->groups_.back().widgets.push_back({label, {text}}); + return label; } @@ -132,6 +138,43 @@ void SettingsLayout::addSeperator() this->addWidget(new Line(false)); } +void SettingsLayout::filterElements(const QString &query) +{ + for (auto &&group : this->groups_) + { + // if group name matches then all should be visible + if (group.name.contains(query, Qt::CaseInsensitive)) + { + for (auto &&widget : group.widgets) + widget.element->show(); + group.title->show(); + } + // check if any match + else + { + auto any = false; + + for (auto &&widget : group.widgets) + { + for (auto &&keyword : widget.keywords) + { + if (keyword.contains(query, Qt::CaseInsensitive)) + { + widget.element->show(); + any = true; + } + else + { + widget.element->hide(); + } + } + } + + group.title->setVisible(any); + } + } +} + GeneralPage::GeneralPage() : SettingsPage("General", ":/settings/about.svg") { @@ -141,6 +184,7 @@ GeneralPage::GeneralPage() y->addWidget(scroll); auto x = new QHBoxLayout; auto layout = new SettingsLayout; + this->settingsLayout_ = layout; x->addLayout(layout, 0); x->addStretch(1); auto z = new QFrame; @@ -155,6 +199,12 @@ GeneralPage::GeneralPage() this->initExtra(); } +void GeneralPage::filterElements(const QString &query) +{ + if (this->settingsLayout_) + this->settingsLayout_->filterElements(query); +} + void GeneralPage::initLayout(SettingsLayout &layout) { auto &s = *getSettings(); @@ -284,7 +334,7 @@ void GeneralPage::initLayout(SettingsLayout &layout) layout.addCheckbox("Chatterino", getSettings()->showBadgesChatterino); layout.addTitle("Chat title"); - layout.addWidget(new QLabel("In live channels show:")); + layout.addDescription("In live channels show:"); layout.addCheckbox("Uptime", s.headerUptime); layout.addCheckbox("Viewer count", s.headerViewerCount); layout.addCheckbox("Category", s.headerGame); @@ -345,10 +395,10 @@ void GeneralPage::initLayout(SettingsLayout &layout) void GeneralPage::initExtra() { /// update cache path - if (this->cachePath) + if (this->cachePath_) { getSettings()->cachePath.connect( - [cachePath = this->cachePath](const auto &, auto) mutable { + [cachePath = this->cachePath_](const auto &, auto) mutable { QString newPath = getPaths()->cacheDirectory(); QString pathShortened = "Current location: widgets; + }; + + std::vector groups_; std::vector managedConnections_; }; @@ -154,13 +156,16 @@ class GeneralPage : public SettingsPage public: GeneralPage(); + void filterElements(const QString &query); + private: void initLayout(SettingsLayout &layout); void initExtra(); QString getFont(const DropdownArgs &args) const; - DescriptionLabel *cachePath{}; + DescriptionLabel *cachePath_{}; + SettingsLayout *settingsLayout_{}; }; } // namespace chatterino diff --git a/src/widgets/settingspages/SettingsPage.cpp b/src/widgets/settingspages/SettingsPage.cpp index 01af44538..4b0d147f1 100644 --- a/src/widgets/settingspages/SettingsPage.cpp +++ b/src/widgets/settingspages/SettingsPage.cpp @@ -5,15 +5,56 @@ #include #include +#include namespace chatterino { +void filterItemsRec(QObject *object, const QString &query) +{ + for (auto &&child : object->children()) + { + auto setOpacity = [=](auto *widget, bool condition) { + widget->greyedOut = !condition; + widget->update(); + }; + + if (auto x = dynamic_cast(child); x) + { + setOpacity(x, x->text().contains(query, Qt::CaseInsensitive)); + } + else if (auto x = dynamic_cast(child); x) + { + setOpacity(x, x->text().contains(query, Qt::CaseInsensitive)); + } + else if (auto x = dynamic_cast(child); x) + { + setOpacity(x, [=]() { + for (int i = 0; i < x->count(); i++) + { + if (x->itemText(i).contains(query, Qt::CaseInsensitive)) + return true; + } + return false; + }()); + } + else + { + filterItemsRec(child, query); + } + } +} + SettingsPage::SettingsPage(const QString &name, const QString &iconResource) : name_(name) , iconResource_(iconResource) { } +void SettingsPage::filterElements(const QString &query) +{ + filterItemsRec(this, query); +} + const QString &SettingsPage::getName() { return this->name_; @@ -42,7 +83,7 @@ void SettingsPage::cancel() QCheckBox *SettingsPage::createCheckBox( const QString &text, pajlada::Settings::Setting &setting) { - QCheckBox *checkbox = new QCheckBox(text); + QCheckBox *checkbox = new SCheckBox(text); // update when setting changes setting.connect( @@ -64,7 +105,7 @@ QCheckBox *SettingsPage::createCheckBox( QComboBox *SettingsPage::createComboBox( const QStringList &items, pajlada::Settings::Setting &setting) { - QComboBox *combo = new QComboBox(); + QComboBox *combo = new SComboBox(); // update setting on toogle combo->addItems(items); diff --git a/src/widgets/settingspages/SettingsPage.hpp b/src/widgets/settingspages/SettingsPage.hpp index 79d3a7240..1678b34f8 100644 --- a/src/widgets/settingspages/SettingsPage.hpp +++ b/src/widgets/settingspages/SettingsPage.hpp @@ -8,8 +8,35 @@ #include "singletons/Settings.hpp" +#define SETTINGS_PAGE_WIDGET_BOILERPLATE(type, parent) \ + class type : public parent \ + { \ + using parent::parent; \ + \ + public: \ + bool greyedOut{}; \ + \ + protected: \ + void paintEvent(QPaintEvent *e) override \ + { \ + parent::paintEvent(e); \ + \ + if (this->greyedOut) \ + { \ + QPainter painter(this); \ + QColor color = QColor("#222222"); \ + color.setAlphaF(0.7); \ + painter.fillRect(this->rect(), color); \ + } \ + } \ + }; + namespace chatterino { +SETTINGS_PAGE_WIDGET_BOILERPLATE(SCheckBox, QCheckBox) +SETTINGS_PAGE_WIDGET_BOILERPLATE(SLabel, QLabel) +SETTINGS_PAGE_WIDGET_BOILERPLATE(SComboBox, QComboBox) + class SettingsDialogTab; class SettingsPage : public QFrame @@ -22,6 +49,8 @@ public: const QString &getName(); const QString &getIconResource(); + virtual void filterElements(const QString &query); + SettingsDialogTab *tab() const; void setTab(SettingsDialogTab *tab);