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);