From dda10d35764c8417c19020a6d3264dc8984994a9 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Fri, 3 Jan 2025 14:49:55 +1000 Subject: [PATCH] Qt: Add search box to hotkey settings --- src/duckstation-qt/hotkeysettingswidget.cpp | 101 ++++++++++++++++---- src/duckstation-qt/hotkeysettingswidget.h | 37 ++++++- src/duckstation-qt/inputbindingwidgets.cpp | 6 +- 3 files changed, 120 insertions(+), 24 deletions(-) diff --git a/src/duckstation-qt/hotkeysettingswidget.cpp b/src/duckstation-qt/hotkeysettingswidget.cpp index 2b4f832d20..3e066f9743 100644 --- a/src/duckstation-qt/hotkeysettingswidget.cpp +++ b/src/duckstation-qt/hotkeysettingswidget.cpp @@ -1,14 +1,18 @@ -// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #include "hotkeysettingswidget.h" #include "controllersettingswindow.h" -#include "util/input_manager.h" #include "inputbindingwidgets.h" #include "qtutils.h" #include "settingwidgetbinder.h" + +#include "util/input_manager.h" + +#include #include #include +#include #include #include @@ -20,13 +24,36 @@ HotkeySettingsWidget::HotkeySettingsWidget(QWidget* parent, ControllerSettingsWi HotkeySettingsWidget::~HotkeySettingsWidget() = default; +HotkeySettingsWidget::Container::Container(QWidget* parent) : QWidget(parent) +{ + m_search = new QLineEdit(this); + m_search->setPlaceholderText(tr("Search...")); +} + +HotkeySettingsWidget::Container::~Container() = default; + +void HotkeySettingsWidget::Container::resizeEvent(QResizeEvent* event) +{ + QWidget::resizeEvent(event); + repositionSearchBox(); +} + +void HotkeySettingsWidget::Container::repositionSearchBox() +{ + constexpr int box_width = 300; + constexpr int box_padding = 8; + const int x = std::max(width() - box_width - box_padding, 0); + const int h = m_search->height(); + m_search->setGeometry(x, box_padding, box_width, h); +} + void HotkeySettingsWidget::createUi() { QGridLayout* layout = new QGridLayout(this); layout->setContentsMargins(0, 0, 0, 0); m_scroll_area = new QScrollArea(this); - m_container = new QWidget(m_scroll_area); + m_container = new Container(m_scroll_area); m_layout = new QVBoxLayout(m_container); m_scroll_area->setWidget(m_container); m_scroll_area->setWidgetResizable(true); @@ -38,6 +65,9 @@ void HotkeySettingsWidget::createUi() layout->addWidget(m_scroll_area, 0, 0, 1, 1); setLayout(layout); + + m_container->searchBox()->raise(); + connect(m_container->searchBox(), &QLineEdit::textChanged, this, &HotkeySettingsWidget::setFilter); } void HotkeySettingsWidget::createButtons() @@ -48,27 +78,35 @@ void HotkeySettingsWidget::createButtons() const QString category(qApp->translate("Hotkeys", hotkey->category)); auto iter = m_categories.find(category); + int target_row = 0; if (iter == m_categories.end()) { - QLabel* label = new QLabel(category, m_container); - QFont label_font(label->font()); + CategoryWidgets cw; + cw.label = new QLabel(category, m_container); + QFont label_font(cw.label->font()); label_font.setPointSizeF(14.0f); - label->setFont(label_font); - m_layout->addWidget(label); - - QLabel* line = new QLabel(m_container); - line->setFrameShape(QFrame::HLine); - line->setFixedHeight(4); - m_layout->addWidget(line); - - QGridLayout* layout = new QGridLayout(); - layout->setContentsMargins(0, 0, 0, 0); - m_layout->addLayout(layout); - iter = m_categories.insert(category, layout); + cw.label->setFont(label_font); + m_layout->addWidget(cw.label); + + cw.line = new QLabel(m_container); + cw.line->setFrameShape(QFrame::HLine); + cw.line->setFixedHeight(4); + m_layout->addWidget(cw.line); + + cw.layout = new QGridLayout(); + cw.layout->setContentsMargins(0, 0, 0, 0); + m_layout->addLayout(cw.layout); + iter = m_categories.insert(category, cw); + + // row count starts at 1 for some reason + target_row = 0; + } + else + { + target_row = iter->layout->rowCount(); } - QGridLayout* layout = *iter; - const int target_row = layout->count() / 2; + QGridLayout* layout = iter->layout; QLabel* label = new QLabel(qApp->translate("Hotkeys", hotkey->display_name), m_container); layout->addWidget(label, target_row, 0); @@ -79,3 +117,28 @@ void HotkeySettingsWidget::createButtons() layout->addWidget(bind, target_row, 1); } } + +void HotkeySettingsWidget::setFilter(const QString& filter) +{ + for (const CategoryWidgets& cw : m_categories) + { + const int row_count = cw.layout->rowCount(); + int visible_row_count = 0; + for (int i = 0; i < row_count; i++) + { + QLabel* label = qobject_cast(cw.layout->itemAtPosition(i, 0)->widget()); + InputBindingWidget* bind = qobject_cast(cw.layout->itemAtPosition(i, 1)->widget()); + if (!label || !bind) + continue; + + const bool visible = (filter.isEmpty() || label->text().indexOf(filter, 0, Qt::CaseInsensitive) >= 0); + label->setVisible(visible); + bind->setVisible(visible); + visible_row_count += static_cast(visible); + } + + const bool heading_visible = (visible_row_count > 0); + cw.label->setVisible(heading_visible); + cw.line->setVisible(heading_visible); + } +} diff --git a/src/duckstation-qt/hotkeysettingswidget.h b/src/duckstation-qt/hotkeysettingswidget.h index 3e54e2c827..09b78af9de 100644 --- a/src/duckstation-qt/hotkeysettingswidget.h +++ b/src/duckstation-qt/hotkeysettingswidget.h @@ -1,13 +1,16 @@ -// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin +// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin // SPDX-License-Identifier: CC-BY-NC-ND-4.0 #pragma once #include #include + #include #include +class QLabel; +class QLineEdit; class QScrollArea; class QGridLayout; class QVBoxLayout; @@ -23,13 +26,41 @@ class HotkeySettingsWidget : public QWidget ~HotkeySettingsWidget(); private: + struct CategoryWidgets + { + QLabel* label; + QLabel* line; + QGridLayout* layout; + }; + + class Container final : public QWidget + { + public: + Container(QWidget* parent); + ~Container() override; + + QLineEdit* searchBox() const { return m_search; } + + void resizeEvent(QResizeEvent* event) override; + + private: + void repositionSearchBox(); + + QLineEdit* m_search; + }; + void createUi(); void createButtons(); +private Q_SLOTS: + void setFilter(const QString& filter); + +private: ControllerSettingsWindow* m_dialog; QScrollArea* m_scroll_area = nullptr; - QWidget* m_container = nullptr; + Container* m_container = nullptr; QVBoxLayout* m_layout = nullptr; + QLineEdit* m_search = nullptr; - QMap m_categories; + QMap m_categories; }; diff --git a/src/duckstation-qt/inputbindingwidgets.cpp b/src/duckstation-qt/inputbindingwidgets.cpp index 45bbd713c6..62a6f492a6 100644 --- a/src/duckstation-qt/inputbindingwidgets.cpp +++ b/src/duckstation-qt/inputbindingwidgets.cpp @@ -87,8 +87,10 @@ void InputBindingWidget::updateText() // fix up accelerators, and if it's too long, ellipsise it if (binding_text.contains('&')) binding_text = binding_text.replace(QStringLiteral("&"), QStringLiteral("&&")); - if (binding_text.length() > 35) - binding_text = binding_text.left(35).append(QStringLiteral("...")); + + const int max_length = (width() < 300) ? 35 : 60; + if (binding_text.length() > max_length) + binding_text = binding_text.left(max_length).append(QStringLiteral("...")); setText(binding_text); setToolTip(QStringLiteral("%1\n\n%2\n%3").arg(binding_text).arg(tr(help_text)).arg(tr(help_clear_text))); }