diff --git a/resources/buttons/search.png b/resources/buttons/search.png new file mode 100644 index 00000000..8671ce64 Binary files /dev/null and b/resources/buttons/search.png differ diff --git a/resources/generate_resources.py b/resources/generate_resources.py index e48795f7..dc0cf184 100755 --- a/resources/generate_resources.py +++ b/resources/generate_resources.py @@ -18,10 +18,10 @@ def isNotIgnored(file): return file.as_posix() not in ignored_files -all_files = list(filter(isNotIgnored, \ - filter(Path.is_file, Path('.').glob('**/*')))) -image_files = list(filter(isNotIgnored, \ - filter(Path.is_file, Path('.').glob('**/*.png')))) +all_files = sorted(list(filter(isNotIgnored, \ + filter(Path.is_file, Path('.').glob('**/*'))))) +image_files = sorted(list(filter(isNotIgnored, \ + filter(Path.is_file, Path('.').glob('**/*.png'))))) with open('./resources_autogenerated.qrc', 'w') as out: out.write(resources_header) diff --git a/resources/qss/settings.qss b/resources/qss/settings.qss index 54f1b599..590dff5f 100644 --- a/resources/qss/settings.qss +++ b/resources/qss/settings.qss @@ -8,7 +8,7 @@ QCheckBox::indicator { } chatterino--ComboBox { - width: 100px; + width: 120px; } QScrollArea { @@ -27,19 +27,19 @@ QComboBox QFrame { chatterino--SettingsPage { background: #222; - border: 1px solid #555; + /*border: 1px solid #555; + border-left: none;*/ +} + +chatterino--PageHeader { + margin-bottom: 12px; } 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/resources/resources_autogenerated.qrc b/resources/resources_autogenerated.qrc index e1ffa331..9f0569e3 100644 --- a/resources/resources_autogenerated.qrc +++ b/resources/resources_autogenerated.qrc @@ -1,86 +1,88 @@ - icon.png - emojidata.txt - chatterino.desktop - error.png - .gitignore - tlds.txt - contributors.txt - pajaDank.png - chatterino.icns - icon.ico - emoji.json - buttons/mod.png - buttons/copyDark.svg - buttons/modModeDisabled.png - buttons/unmod.png + .gitignore + avatars/fourtf.png + avatars/pajlada.png + buttons/addSplit.png buttons/addSplitDark.png + buttons/ban.png + buttons/banRed.png + buttons/copyDark.png + buttons/copyDark.svg + buttons/copyDarkTheme.png + buttons/copyLight.png + buttons/copyLight.svg + buttons/emote.svg + buttons/emoteDark.svg + buttons/menuDark.png + buttons/menuLight.png + buttons/mod.png + buttons/modModeDisabled.png + buttons/modModeDisabled2.png + buttons/modModeEnabled.png + buttons/modModeEnabled2.png + buttons/search.png buttons/timeout.png buttons/trashCan.png buttons/trashcan.svg - buttons/modModeEnabled.png - buttons/copyLight.svg - buttons/modModeEnabled2.png - buttons/banRed.png - buttons/ban.png - buttons/emoteDark.svg - buttons/menuLight.png - buttons/emote.svg - buttons/update.png - buttons/addSplit.png - buttons/menuDark.png - buttons/updateError.png buttons/unban.png - buttons/copyLight.png - buttons/modModeDisabled2.png - buttons/copyDark.png + buttons/unmod.png + buttons/update.png + buttons/updateError.png + chatterino.desktop + chatterino.icns + contributors.txt + emoji.json + emojidata.txt + error.png examples/moving.gif examples/splitting.gif - twitch/prime.png - twitch/vip.png - twitch/cheer1.png - twitch/admin.png - twitch/broadcaster.png - twitch/verified.png - twitch/moderator.png - twitch/globalmod.png - twitch/automod.png - twitch/subscriber.png - twitch/staff.png - twitch/turbo.png - licenses/qt_lgpl-3.0.txt - licenses/emoji-data-source.txt - licenses/pajlada_settings.txt - licenses/openssl.txt - licenses/pajlada_signals.txt - licenses/rapidjson.txt - licenses/libcommuni_BSD3.txt + icon.ico + icon.png licenses/boost_boost.txt - licenses/websocketpp.txt + licenses/emoji-data-source.txt licenses/fmt_bsd2.txt - settings/aboutlogo.png - settings/ignore.svg - settings/notification2.svg - settings/theme.svg - settings/externaltools.svg - settings/advanced.svg + licenses/libcommuni_BSD3.txt + licenses/openssl.txt + licenses/pajlada_settings.txt + licenses/pajlada_signals.txt + licenses/qt_lgpl-3.0.txt + licenses/rapidjson.txt + licenses/websocketpp.txt + pajaDank.png + qss/settings.qss settings/about.svg - settings/notifications.svg - settings/behave.svg + settings/aboutlogo.png settings/accounts.svg - settings/emote.svg + settings/advanced.svg + settings/behave.svg + settings/browser.svg settings/commands.svg + settings/emote.svg + settings/externaltools.svg + settings/ignore.svg settings/keybinds.svg settings/moderation.svg - settings/browser.svg - avatars/pajlada.png - avatars/fourtf.png - qss/settings.qss + settings/notification2.svg + settings/notifications.svg + settings/theme.svg sounds/ping2.wav + split/down.png split/left.png split/move.png split/right.png - split/down.png split/up.png + tlds.txt + twitch/admin.png + twitch/automod.png + twitch/broadcaster.png + twitch/cheer1.png + twitch/globalmod.png + twitch/moderator.png + twitch/prime.png + twitch/staff.png + twitch/subscriber.png + twitch/turbo.png + twitch/verified.png + twitch/vip.png \ No newline at end of file diff --git a/src/autogenerated/ResourcesAutogen.cpp b/src/autogenerated/ResourcesAutogen.cpp index 8075ca02..9629a8f0 100644 --- a/src/autogenerated/ResourcesAutogen.cpp +++ b/src/autogenerated/ResourcesAutogen.cpp @@ -11,6 +11,7 @@ Resources2::Resources2() this->buttons.ban = QPixmap(":/buttons/ban.png"); this->buttons.banRed = QPixmap(":/buttons/banRed.png"); this->buttons.copyDark = QPixmap(":/buttons/copyDark.png"); + this->buttons.copyDarkTheme = QPixmap(":/buttons/copyDarkTheme.png"); this->buttons.copyLight = QPixmap(":/buttons/copyLight.png"); this->buttons.menuDark = QPixmap(":/buttons/menuDark.png"); this->buttons.menuLight = QPixmap(":/buttons/menuLight.png"); @@ -19,6 +20,7 @@ Resources2::Resources2() this->buttons.modModeDisabled2 = QPixmap(":/buttons/modModeDisabled2.png"); this->buttons.modModeEnabled = QPixmap(":/buttons/modModeEnabled.png"); this->buttons.modModeEnabled2 = QPixmap(":/buttons/modModeEnabled2.png"); + this->buttons.search = QPixmap(":/buttons/search.png"); this->buttons.timeout = QPixmap(":/buttons/timeout.png"); this->buttons.trashCan = QPixmap(":/buttons/trashCan.png"); this->buttons.unban = QPixmap(":/buttons/unban.png"); diff --git a/src/autogenerated/ResourcesAutogen.hpp b/src/autogenerated/ResourcesAutogen.hpp index 467cbed9..c6b3dc48 100644 --- a/src/autogenerated/ResourcesAutogen.hpp +++ b/src/autogenerated/ResourcesAutogen.hpp @@ -3,8 +3,7 @@ namespace chatterino { -class Resources2 : public Singleton -{ +class Resources2 : public Singleton { public: Resources2(); @@ -18,6 +17,7 @@ public: QPixmap ban; QPixmap banRed; QPixmap copyDark; + QPixmap copyDarkTheme; QPixmap copyLight; QPixmap menuDark; QPixmap menuLight; @@ -26,6 +26,7 @@ public: QPixmap modModeDisabled2; QPixmap modModeEnabled; QPixmap modModeEnabled2; + QPixmap search; QPixmap timeout; QPixmap trashCan; QPixmap unban; diff --git a/src/widgets/dialogs/SettingsDialog.cpp b/src/widgets/dialogs/SettingsDialog.cpp index 69536bed..ea52df18 100644 --- a/src/widgets/dialogs/SettingsDialog.cpp +++ b/src/widgets/dialogs/SettingsDialog.cpp @@ -1,7 +1,9 @@ #include "widgets/dialogs/SettingsDialog.hpp" #include "Application.hpp" +#include "singletons/Resources.hpp" #include "util/LayoutCreator.hpp" +#include "widgets/helper/Button.hpp" #include "widgets/helper/SettingsDialogTab.hpp" #include "widgets/settingspages/AboutPage.hpp" #include "widgets/settingspages/AccountsPage.hpp" @@ -22,6 +24,7 @@ #include "widgets/settingspages/SpecialChannelsPage.hpp" #include +#include namespace chatterino { @@ -43,39 +46,55 @@ SettingsDialog::SettingsDialog() void SettingsDialog::initUi() { - LayoutCreator layoutCreator(this); + auto outerBox = LayoutCreator(this) + .setLayoutType() + .withoutSpacing(); - // tab pages - layoutCreator.setLayoutType() - .withoutSpacing() - .emplace() + // TOP + auto title = outerBox.emplace(); + auto edit = LayoutCreator(title.getElement()) + .setLayoutType() + .withoutMargin() + .emplace() + .assign(&this->ui_.search); + edit->setPlaceholderText("Find in settings..."); + + QObject::connect(edit.getElement(), &QLineEdit::textChanged, this, + &SettingsDialog::filterElements); + + // CENTER + auto centerBox = + outerBox.emplace().withoutMargin().withoutSpacing(); + + // left side (tabs) + centerBox.emplace() .assign(&this->ui_.tabContainerContainer) - .emplace() + .setLayoutType() .withoutMargin() .assign(&this->ui_.tabContainer); - this->ui_.tabContainerContainer->layout()->setContentsMargins(8, 8, 0, 39); - - this->layout()->setSpacing(0); - - // right side layout - auto right = layoutCreator.emplace().withoutMargin(); + // right side (pages) + auto right = + centerBox.emplace().withoutMargin().withoutSpacing(); { right.emplace() .assign(&this->ui_.pageStack) .withoutMargin(); - - auto buttons = right.emplace(Qt::Horizontal); - { - this->ui_.okButton = - buttons->addButton("Ok", QDialogButtonBox::YesRole); - this->ui_.cancelButton = - buttons->addButton("Cancel", QDialogButtonBox::NoRole); - } } this->ui_.pageStack->setMargin(0); + outerBox->addSpacing(12); + + // BOTTOM + auto buttons = outerBox.emplace(Qt::Horizontal); + { + this->ui_.okButton = + buttons->addButton("Ok", QDialogButtonBox::YesRole); + this->ui_.cancelButton = + buttons->addButton("Cancel", QDialogButtonBox::NoRole); + } + // ---- misc this->ui_.tabContainerContainer->setObjectName("tabWidget"); this->ui_.pageStack->setObjectName("pages"); @@ -86,6 +105,50 @@ void SettingsDialog::initUi() &SettingsDialog::onCancelClicked); } +void SettingsDialog::filterElements(const QString &text) +{ + // filter elements and hide pages + for (auto &&page : this->pages_) + { + // filterElements returns true if anything on the page matches the search query + page->tab()->setVisible(page->filterElements(text)); + } + + // find next visible page + if (this->lastSelectedByUser_ && this->lastSelectedByUser_->isVisible()) + { + this->selectTab(this->lastSelectedByUser_, false); + } + else if (!this->selectedTab_->isVisible()) + { + for (auto &&tab : this->tabs_) + { + if (tab->isVisible()) + { + this->selectTab(tab, false); + break; + } + } + } + + // remove duplicate spaces + bool shouldShowSpace = false; + + for (int i = 0; i < this->ui_.tabContainer->count(); i++) + { + auto item = this->ui_.tabContainer->itemAt(i); + if (auto x = dynamic_cast(item); x) + { + x->changeSize(10, shouldShowSpace ? int(16 * this->scale()) : 0); + shouldShowSpace = false; + } + else if (item->widget()) + { + shouldShowSpace |= item->widget()->isVisible(); + } + } +} + SettingsDialog *SettingsDialog::getHandle() { return SettingsDialog::handle; @@ -96,7 +159,7 @@ void SettingsDialog::addTabs() this->ui_.tabContainer->setMargin(0); this->ui_.tabContainer->setSpacing(0); - this->ui_.tabContainer->addSpacing(16); + this->ui_.tabContainer->setContentsMargins(0, 20, 0, 20); this->addTab(new GeneralPage); @@ -104,32 +167,22 @@ 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); this->ui_.tabContainer->addStretch(1); this->addTab(new AboutPage, Qt::AlignBottom); - this->ui_.tabContainer->addSpacing(16); } void SettingsDialog::addTab(SettingsPage *page, Qt::Alignment alignment) @@ -140,6 +193,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) { @@ -147,7 +201,7 @@ void SettingsDialog::addTab(SettingsPage *page, Qt::Alignment alignment) } } -void SettingsDialog::selectTab(SettingsDialogTab *tab) +void SettingsDialog::selectTab(SettingsDialogTab *tab, bool byUser) { this->ui_.pageStack->setCurrentWidget(tab->getSettingsPage()); @@ -159,10 +213,12 @@ void SettingsDialog::selectTab(SettingsDialogTab *tab) tab->setSelected(true); tab->setStyleSheet("background: #222; color: #4FC3F7;" - "border-left: 1px solid #444;" - "border-top: 1px solid #444;" - "border-bottom: 1px solid #444;"); + "/*border: 1px solid #555; border-right: none;*/"); this->selectedTab_ = tab; + if (byUser) + { + this->lastSelectedByUser_ = tab; + } } void SettingsDialog::selectPage(SettingsPage *page) diff --git a/src/widgets/dialogs/SettingsDialog.hpp b/src/widgets/dialogs/SettingsDialog.hpp index e5bc0659..ff409fec 100644 --- a/src/widgets/dialogs/SettingsDialog.hpp +++ b/src/widgets/dialogs/SettingsDialog.hpp @@ -8,12 +8,19 @@ #include #include +class QLineEdit; + namespace chatterino { class SettingsPage; class SettingsDialogTab; class ModerationPage; +class PageHeader : public QFrame +{ + Q_OBJECT +}; + enum class SettingsDialogPreference { NoPreference, Accounts, @@ -41,8 +48,9 @@ private: void initUi(); void addTabs(); void addTab(SettingsPage *page, Qt::Alignment alignment = Qt::AlignTop); - void selectTab(SettingsDialogTab *tab); + void selectTab(SettingsDialogTab *tab, bool byUser = true); void selectPage(SettingsPage *page); + void filterElements(const QString &query); void onOkClicked(); void onCancelClicked(); @@ -54,9 +62,12 @@ private: QPushButton *okButton{}; QPushButton *cancelButton{}; ModerationPage *moderationPage{}; + QLineEdit *search{}; } ui_; std::vector tabs_; + std::vector pages_; SettingsDialogTab *selectedTab_{}; + SettingsDialogTab *lastSelectedByUser_{}; friend class SettingsDialogTab; }; diff --git a/src/widgets/helper/SettingsDialogTab.cpp b/src/widgets/helper/SettingsDialogTab.cpp index 0474126c..8089bf80 100644 --- a/src/widgets/helper/SettingsDialogTab.cpp +++ b/src/widgets/helper/SettingsDialogTab.cpp @@ -68,6 +68,8 @@ void SettingsDialogTab::mousePressEvent(QMouseEvent *event) } this->dialog_->selectTab(this); + + this->setFocus(); } } // namespace chatterino diff --git a/src/widgets/settingspages/CommandPage.cpp b/src/widgets/settingspages/CommandPage.cpp index 60b112e1..be631baa 100644 --- a/src/widgets/settingspages/CommandPage.cpp +++ b/src/widgets/settingspages/CommandPage.cpp @@ -38,7 +38,7 @@ CommandPage::CommandPage() auto app = getApp(); LayoutCreator layoutCreator(this); - auto layout = layoutCreator.emplace().withoutMargin(); + auto layout = layoutCreator.setLayoutType(); EditableModelView *view = layout.emplace(app->commands->createModel(nullptr)) diff --git a/src/widgets/settingspages/GeneralPage.cpp b/src/widgets/settingspages/GeneralPage.cpp index a9b74ad3..19a8d80b 100644 --- a/src/widgets/settingspages/GeneralPage.cpp +++ b/src/widgets/settingspages/GeneralPage.cpp @@ -38,20 +38,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; } @@ -73,6 +66,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; } @@ -84,11 +81,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; } @@ -126,6 +129,9 @@ DescriptionLabel *SettingsLayout::addDescription(const QString &text) this->addWidget(label); + // groups + this->groups_.back().widgets.push_back({label, {text}}); + return label; } @@ -134,6 +140,64 @@ void SettingsLayout::addSeperator() this->addWidget(new Line(false)); } +bool SettingsLayout::filterElements(const QString &query) +{ + bool any{}; + + for (auto &&group : this->groups_) + { + // if a description in a group matches `query` then show the entire group + bool descriptionMatches{}; + for (auto &&widget : group.widgets) + { + if (auto x = dynamic_cast(widget.element); x) + { + if (x->text().contains(query, Qt::CaseInsensitive)) + { + descriptionMatches = true; + break; + } + } + } + + // if group name matches then all should be visible + if (group.name.contains(query, Qt::CaseInsensitive) || + descriptionMatches) + { + for (auto &&widget : group.widgets) + widget.element->show(); + group.title->show(); + any = true; + } + // check if any match + else + { + auto groupAny = false; + + for (auto &&widget : group.widgets) + { + for (auto &&keyword : widget.keywords) + { + if (keyword.contains(query, Qt::CaseInsensitive)) + { + widget.element->show(); + groupAny = true; + } + else + { + widget.element->hide(); + } + } + } + + group.title->setVisible(groupAny); + any |= groupAny; + } + } + + return any; +} + GeneralPage::GeneralPage() : SettingsPage("General", ":/settings/about.svg") { @@ -143,6 +207,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; @@ -157,6 +222,16 @@ GeneralPage::GeneralPage() this->initExtra(); } +bool GeneralPage::filterElements(const QString &query) +{ + if (this->settingsLayout_) + return this->settingsLayout_->filterElements(query) || + this->name_.contains(query, Qt::CaseInsensitive) || + query.isEmpty(); + else + return false; +} + void GeneralPage::initLayout(SettingsLayout &layout) { auto &s = *getSettings(); @@ -353,15 +428,19 @@ void GeneralPage::initLayout(SettingsLayout &layout) "store in this directory."); layout.addWidget(makeOpenSettingDirButton()); -} // namespace chatterino + // invisible element for width + auto inv = new BaseWidget(this); + inv->setScaleIndependantWidth(500); + layout.addWidget(inv); +} 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(); + bool 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/KeyboardSettingsPage.cpp b/src/widgets/settingspages/KeyboardSettingsPage.cpp index 580848b3..c81754b2 100644 --- a/src/widgets/settingspages/KeyboardSettingsPage.cpp +++ b/src/widgets/settingspages/KeyboardSettingsPage.cpp @@ -13,7 +13,7 @@ KeyboardSettingsPage::KeyboardSettingsPage() auto layout = LayoutCreator(this).setLayoutType(); - auto form = layout.emplace(); + auto form = layout.emplace().withoutMargin(); form->addRow(new QLabel("Hold Ctrl"), new QLabel("Show resize handles")); form->addRow(new QLabel("Hold Ctrl + Alt"), diff --git a/src/widgets/settingspages/SettingsPage.cpp b/src/widgets/settingspages/SettingsPage.cpp index 01af4453..ca015766 100644 --- a/src/widgets/settingspages/SettingsPage.cpp +++ b/src/widgets/settingspages/SettingsPage.cpp @@ -5,15 +5,77 @@ #include #include +#include namespace chatterino { +bool filterItemsRec(QObject *object, const QString &query) +{ + bool any{}; + + for (auto &&child : object->children()) + { + auto setOpacity = [&](auto *widget, bool condition) { + any |= 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 if (auto x = dynamic_cast(child); x) + { + for (int i = 0; i < x->count(); i++) + { + bool tabAny{}; + + if (x->tabText(i).contains(query, Qt::CaseInsensitive)) + { + tabAny = true; + } + auto widget = x->widget(i); + tabAny |= filterItemsRec(widget, query); + + any |= tabAny; + } + } + else + { + any |= filterItemsRec(child, query); + } + } + return any; +} + SettingsPage::SettingsPage(const QString &name, const QString &iconResource) : name_(name) , iconResource_(iconResource) { } +bool SettingsPage::filterElements(const QString &query) +{ + return filterItemsRec(this, query) || query.isEmpty() || + this->name_.contains(query, Qt::CaseInsensitive); +} + const QString &SettingsPage::getName() { return this->name_; @@ -42,7 +104,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 +126,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 79d3a724..88852d20 100644 --- a/src/widgets/settingspages/SettingsPage.hpp +++ b/src/widgets/settingspages/SettingsPage.hpp @@ -8,8 +8,38 @@ #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 { +// S* widgets are the same as their Q* counterparts, +// but they can be greyed out and will be if you search. +SETTINGS_PAGE_WIDGET_BOILERPLATE(SCheckBox, QCheckBox) +SETTINGS_PAGE_WIDGET_BOILERPLATE(SLabel, QLabel) +SETTINGS_PAGE_WIDGET_BOILERPLATE(SComboBox, QComboBox) +SETTINGS_PAGE_WIDGET_BOILERPLATE(SPushButton, QPushButton) + class SettingsDialogTab; class SettingsPage : public QFrame @@ -22,6 +52,8 @@ public: const QString &getName(); const QString &getIconResource(); + virtual bool filterElements(const QString &query); + SettingsDialogTab *tab() const; void setTab(SettingsDialogTab *tab);