Qt: Improve text elision in InputBindingWidget (#3629)

This commit is contained in:
Davide Pesavento
2025-11-19 23:03:29 -05:00
committed by GitHub
parent bea07e71af
commit b949c17cc8
3 changed files with 41 additions and 23 deletions

View File

@@ -139,7 +139,7 @@ void HotkeySettingsWidget::createButtons()
QWidget* const row = new QWidget(m_container);
row->setAutoFillBackground(true);
row->setBackgroundRole((((iter->layout->count()) % 2) == 0) ? QPalette::Base : QPalette::AlternateBase);
row->setBackgroundRole(((iter->layout->count() % 2) == 0) ? QPalette::Base : QPalette::AlternateBase);
row->setPalette(row_palette);
iter->layout->addWidget(row);
@@ -150,7 +150,7 @@ void HotkeySettingsWidget::createButtons()
InputBindingWidget* const bind = new InputBindingWidget(row, m_dialog->getEditingSettingsInterface(),
InputBindingInfo::Type::Button, "Hotkeys", hotkey->name);
bind->setMinimumWidth(300);
bind->setFixedWidth(300);
row_layout->addWidget(bind);
}
}

View File

@@ -31,8 +31,7 @@ InputBindingWidget::InputBindingWidget(QWidget* parent, SettingsInterface* sif,
std::string section_name, std::string key_name)
: QPushButton(parent)
{
setMinimumWidth(220);
setMaximumWidth(220);
setFixedWidth(220);
connect(this, &QPushButton::clicked, this, &InputBindingWidget::onClicked);
@@ -61,7 +60,22 @@ void InputBindingWidget::initialize(SettingsInterface* sif, InputBindingInfo::Ty
reloadBinding();
}
void InputBindingWidget::updateText()
void InputBindingWidget::updateElidedText()
{
// https://github.com/qt/qtbase/blob/5dbb3b358950726447765e4fea7feb040a303860/src/widgets/styles/qcommonstyle.cpp#L4867
const int button_margin = style()->pixelMetric(QStyle::PM_ButtonMargin, nullptr, this);
const int frame_width = style()->pixelMetric(QStyle::PM_DefaultFrameWidth, nullptr, this);
const int text_width = std::max(1, width() - button_margin - frame_width * 2);
QString elided = fontMetrics().elidedText(m_full_text, Qt::ElideMiddle, text_width);
// fix up accelerators
if (elided.contains('&'))
elided = elided.replace(QStringLiteral("&"), QStringLiteral("&&"));
setText(elided);
}
void InputBindingWidget::updateTextAndToolTip()
{
static constexpr const char* help_text =
QT_TR_NOOP("Left-click to change binding.\nShift-click to set multiple bindings.");
@@ -69,11 +83,13 @@ void InputBindingWidget::updateText()
if (m_bindings.empty())
{
m_full_text.clear();
setText(QString());
setToolTip(QStringLiteral("%1\n\n%2").arg(tr("No binding set.")).arg(tr(help_text)));
}
else if (m_bindings.size() > 1)
{
m_full_text.clear();
setText(tr("%n bindings", "", static_cast<int>(m_bindings.size())));
// keep the full thing for the tooltip
@@ -82,19 +98,9 @@ void InputBindingWidget::updateText()
}
else
{
QString binding_text(QString::fromStdString(m_bindings[0]));
// fix up accelerators
if (binding_text.contains('&'))
binding_text = binding_text.replace(QStringLiteral("&"), QStringLiteral("&&"));
setToolTip(QStringLiteral("%1\n\n%2\n%3").arg(binding_text).arg(tr(help_text)).arg(tr(help_clear_text)));
// if it's too long, ellipsise it
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);
m_full_text = QString::fromStdString(m_bindings[0]);
updateElidedText();
setToolTip(QStringLiteral("%1\n\n%2\n%3").arg(m_full_text).arg(tr(help_text)).arg(tr(help_clear_text)));
}
}
@@ -213,6 +219,14 @@ void InputBindingWidget::mouseReleaseEvent(QMouseEvent* e)
QPushButton::mouseReleaseEvent(e);
}
void InputBindingWidget::resizeEvent(QResizeEvent* e)
{
if (!m_full_text.isEmpty())
updateElidedText();
QPushButton::resizeEvent(e);
}
void InputBindingWidget::setNewBinding()
{
if (m_new_bindings.empty())
@@ -266,7 +280,7 @@ void InputBindingWidget::reloadBinding()
{
m_bindings = m_sif ? m_sif->GetStringList(m_section_name.c_str(), m_key_name.c_str()) :
Host::GetBaseStringListSetting(m_section_name.c_str(), m_key_name.c_str());
updateText();
updateTextAndToolTip();
}
void InputBindingWidget::onClicked()
@@ -299,6 +313,7 @@ void InputBindingWidget::onInputListenTimerTimeout()
return;
}
m_full_text.clear();
setText(tr("Push Button/Axis... [%1]").arg(m_input_listen_remaining_seconds));
}
@@ -311,10 +326,10 @@ void InputBindingWidget::startListeningForInput(u32 timeout_in_seconds)
m_input_listen_timer = new QTimer(this);
m_input_listen_timer->setSingleShot(false);
m_input_listen_timer->start(1000);
m_input_listen_timer->connect(m_input_listen_timer, &QTimer::timeout, this,
&InputBindingWidget::onInputListenTimerTimeout);
m_input_listen_timer->callOnTimeout(this, &InputBindingWidget::onInputListenTimerTimeout);
m_input_listen_remaining_seconds = timeout_in_seconds;
m_full_text.clear();
setText(tr("Push Button/Axis... [%1]").arg(m_input_listen_remaining_seconds));
installEventFilter(this);

View File

@@ -40,6 +40,7 @@ protected:
virtual bool eventFilter(QObject* watched, QEvent* event) override;
virtual bool event(QEvent* event) override;
virtual void mouseReleaseEvent(QMouseEvent* e) override;
virtual void resizeEvent(QResizeEvent* e) override;
virtual void startListeningForInput(u32 timeout_in_seconds);
virtual void stopListeningForInput();
@@ -47,7 +48,8 @@ protected:
bool isListeningForInput() const { return m_input_listen_timer != nullptr; }
void setNewBinding();
void updateText();
void updateElidedText();
void updateTextAndToolTip();
void hookInputManager();
void unhookInputManager();
@@ -65,6 +67,7 @@ protected:
std::vector<std::string> m_bindings;
std::vector<InputBindingKey> m_new_bindings;
std::vector<std::pair<InputBindingKey, std::pair<float, float>>> m_value_ranges;
QString m_full_text;
QTimer* m_input_listen_timer = nullptr;
u32 m_input_listen_remaining_seconds = 0;
QPoint m_input_listen_start_position{};