mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-30 09:35:40 +00:00
Qt: Add "Clear All" and "Rebind All" to controller bindings
This commit is contained in:
parent
45050709f2
commit
ad6e4cb6e4
|
@ -22,6 +22,15 @@ InputBindingWidget::~InputBindingWidget()
|
||||||
Q_ASSERT(!isListeningForInput());
|
Q_ASSERT(!isListeningForInput());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InputBindingWidget::beginRebindAll()
|
||||||
|
{
|
||||||
|
m_is_binding_all = true;
|
||||||
|
if (isListeningForInput())
|
||||||
|
stopListeningForInput();
|
||||||
|
|
||||||
|
startListeningForInput(TIMEOUT_FOR_ALL_BINDING);
|
||||||
|
}
|
||||||
|
|
||||||
bool InputBindingWidget::eventFilter(QObject* watched, QEvent* event)
|
bool InputBindingWidget::eventFilter(QObject* watched, QEvent* event)
|
||||||
{
|
{
|
||||||
const QEvent::Type event_type = event->type();
|
const QEvent::Type event_type = event->type();
|
||||||
|
@ -71,7 +80,7 @@ void InputBindingWidget::onPressed()
|
||||||
if (isListeningForInput())
|
if (isListeningForInput())
|
||||||
stopListeningForInput();
|
stopListeningForInput();
|
||||||
|
|
||||||
startListeningForInput();
|
startListeningForInput(TIMEOUT_FOR_SINGLE_BINDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputBindingWidget::onInputListenTimerTimeout()
|
void InputBindingWidget::onInputListenTimerTimeout()
|
||||||
|
@ -86,7 +95,7 @@ void InputBindingWidget::onInputListenTimerTimeout()
|
||||||
setText(tr("Push Button/Axis... [%1]").arg(m_input_listen_remaining_seconds));
|
setText(tr("Push Button/Axis... [%1]").arg(m_input_listen_remaining_seconds));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputBindingWidget::startListeningForInput()
|
void InputBindingWidget::startListeningForInput(u32 timeout_in_seconds)
|
||||||
{
|
{
|
||||||
m_input_listen_timer = new QTimer(this);
|
m_input_listen_timer = new QTimer(this);
|
||||||
m_input_listen_timer->setSingleShot(false);
|
m_input_listen_timer->setSingleShot(false);
|
||||||
|
@ -94,7 +103,7 @@ void InputBindingWidget::startListeningForInput()
|
||||||
|
|
||||||
m_input_listen_timer->connect(m_input_listen_timer, &QTimer::timeout, this,
|
m_input_listen_timer->connect(m_input_listen_timer, &QTimer::timeout, this,
|
||||||
&InputBindingWidget::onInputListenTimerTimeout);
|
&InputBindingWidget::onInputListenTimerTimeout);
|
||||||
m_input_listen_remaining_seconds = 5;
|
m_input_listen_remaining_seconds = timeout_in_seconds;
|
||||||
setText(tr("Push Button/Axis... [%1]").arg(m_input_listen_remaining_seconds));
|
setText(tr("Push Button/Axis... [%1]").arg(m_input_listen_remaining_seconds));
|
||||||
|
|
||||||
installEventFilter(this);
|
installEventFilter(this);
|
||||||
|
@ -111,6 +120,10 @@ void InputBindingWidget::stopListeningForInput()
|
||||||
releaseMouse();
|
releaseMouse();
|
||||||
releaseKeyboard();
|
releaseKeyboard();
|
||||||
removeEventFilter(this);
|
removeEventFilter(this);
|
||||||
|
|
||||||
|
if (m_is_binding_all && m_next_widget)
|
||||||
|
m_next_widget->beginRebindAll();
|
||||||
|
m_is_binding_all = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputButtonBindingWidget::InputButtonBindingWidget(QtHostInterface* host_interface, QString setting_name,
|
InputButtonBindingWidget::InputButtonBindingWidget(QtHostInterface* host_interface, QString setting_name,
|
||||||
|
@ -203,9 +216,9 @@ void InputButtonBindingWidget::bindToControllerButton(int controller_index, int
|
||||||
stopListeningForInput();
|
stopListeningForInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputButtonBindingWidget::startListeningForInput()
|
void InputButtonBindingWidget::startListeningForInput(u32 timeout_in_seconds)
|
||||||
{
|
{
|
||||||
InputBindingWidget::startListeningForInput();
|
InputBindingWidget::startListeningForInput(timeout_in_seconds);
|
||||||
hookControllerInput();
|
hookControllerInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,9 +279,9 @@ void InputAxisBindingWidget::bindToControllerAxis(int controller_index, int axis
|
||||||
stopListeningForInput();
|
stopListeningForInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputAxisBindingWidget::startListeningForInput()
|
void InputAxisBindingWidget::startListeningForInput(u32 timeout_in_seconds)
|
||||||
{
|
{
|
||||||
InputBindingWidget::startListeningForInput();
|
InputBindingWidget::startListeningForInput(timeout_in_seconds);
|
||||||
hookControllerInput();
|
hookControllerInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,21 +14,32 @@ public:
|
||||||
InputBindingWidget(QtHostInterface* host_interface, QString setting_name, QWidget* parent);
|
InputBindingWidget(QtHostInterface* host_interface, QString setting_name, QWidget* parent);
|
||||||
~InputBindingWidget();
|
~InputBindingWidget();
|
||||||
|
|
||||||
protected:
|
ALWAYS_INLINE InputBindingWidget* getNextWidget() const { return m_next_widget; }
|
||||||
virtual bool eventFilter(QObject* watched, QEvent* event) override;
|
ALWAYS_INLINE void setNextWidget(InputBindingWidget* widget) { m_next_widget = widget; }
|
||||||
virtual void mouseReleaseEvent(QMouseEvent* e) override;
|
|
||||||
|
public Q_SLOTS:
|
||||||
|
void beginRebindAll();
|
||||||
|
void clearBinding();
|
||||||
|
|
||||||
protected Q_SLOTS:
|
protected Q_SLOTS:
|
||||||
void onPressed();
|
void onPressed();
|
||||||
void onInputListenTimerTimeout();
|
void onInputListenTimerTimeout();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void startListeningForInput();
|
enum : u32
|
||||||
|
{
|
||||||
|
TIMEOUT_FOR_SINGLE_BINDING = 5,
|
||||||
|
TIMEOUT_FOR_ALL_BINDING = 10
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual bool eventFilter(QObject* watched, QEvent* event) override;
|
||||||
|
virtual void mouseReleaseEvent(QMouseEvent* e) override;
|
||||||
|
|
||||||
|
virtual void startListeningForInput(u32 timeout_in_seconds);
|
||||||
virtual void stopListeningForInput();
|
virtual void stopListeningForInput();
|
||||||
|
|
||||||
bool isListeningForInput() const { return m_input_listen_timer != nullptr; }
|
bool isListeningForInput() const { return m_input_listen_timer != nullptr; }
|
||||||
void setNewBinding();
|
void setNewBinding();
|
||||||
void clearBinding();
|
|
||||||
|
|
||||||
QtHostInterface* m_host_interface;
|
QtHostInterface* m_host_interface;
|
||||||
QString m_setting_name;
|
QString m_setting_name;
|
||||||
|
@ -36,6 +47,9 @@ protected:
|
||||||
QString m_new_binding_value;
|
QString m_new_binding_value;
|
||||||
QTimer* m_input_listen_timer = nullptr;
|
QTimer* m_input_listen_timer = nullptr;
|
||||||
u32 m_input_listen_remaining_seconds = 0;
|
u32 m_input_listen_remaining_seconds = 0;
|
||||||
|
|
||||||
|
InputBindingWidget* m_next_widget = nullptr;
|
||||||
|
bool m_is_binding_all = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class InputButtonBindingWidget : public InputBindingWidget
|
class InputButtonBindingWidget : public InputBindingWidget
|
||||||
|
@ -54,7 +68,7 @@ private Q_SLOTS:
|
||||||
void bindToControllerButton(int controller_index, int button_index);
|
void bindToControllerButton(int controller_index, int button_index);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void startListeningForInput() override;
|
void startListeningForInput(u32 timeout_in_seconds) override;
|
||||||
void stopListeningForInput() override;
|
void stopListeningForInput() override;
|
||||||
void hookControllerInput();
|
void hookControllerInput();
|
||||||
void unhookControllerInput();
|
void unhookControllerInput();
|
||||||
|
@ -72,7 +86,7 @@ private Q_SLOTS:
|
||||||
void bindToControllerAxis(int controller_index, int axis_index);
|
void bindToControllerAxis(int controller_index, int axis_index);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void startListeningForInput() override;
|
void startListeningForInput(u32 timeout_in_seconds) override;
|
||||||
void stopListeningForInput() override;
|
void stopListeningForInput() override;
|
||||||
void hookControllerInput();
|
void hookControllerInput();
|
||||||
void unhookControllerInput();
|
void unhookControllerInput();
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "qtutils.h"
|
#include "qtutils.h"
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QtGui/QKeyEvent>
|
#include <QtGui/QKeyEvent>
|
||||||
|
#include <QtWidgets/QMessageBox>
|
||||||
|
|
||||||
PortSettingsWidget::PortSettingsWidget(QtHostInterface* host_interface, QWidget* parent /* = nullptr */)
|
PortSettingsWidget::PortSettingsWidget(QtHostInterface* host_interface, QWidget* parent /* = nullptr */)
|
||||||
: QWidget(parent), m_host_interface(host_interface)
|
: QWidget(parent), m_host_interface(host_interface)
|
||||||
|
@ -43,6 +44,8 @@ void PortSettingsWidget::createPortSettingsUi(int index, PortSettingsUI* ui)
|
||||||
ui->layout->addWidget(new QLabel(tr("Memory Card Path:"), ui->widget));
|
ui->layout->addWidget(new QLabel(tr("Memory Card Path:"), ui->widget));
|
||||||
ui->layout->addLayout(memory_card_layout);
|
ui->layout->addLayout(memory_card_layout);
|
||||||
|
|
||||||
|
ui->layout->addWidget(new QLabel(tr("Controller Type:"), ui->widget));
|
||||||
|
|
||||||
ui->controller_type = new QComboBox(ui->widget);
|
ui->controller_type = new QComboBox(ui->widget);
|
||||||
for (int i = 0; i < static_cast<int>(ControllerType::Count); i++)
|
for (int i = 0; i < static_cast<int>(ControllerType::Count); i++)
|
||||||
{
|
{
|
||||||
|
@ -58,7 +61,7 @@ void PortSettingsWidget::createPortSettingsUi(int index, PortSettingsUI* ui)
|
||||||
ui->controller_type->setCurrentIndex(static_cast<int>(ctype));
|
ui->controller_type->setCurrentIndex(static_cast<int>(ctype));
|
||||||
connect(ui->controller_type, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
connect(ui->controller_type, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
||||||
[this, index]() { onControllerTypeChanged(index); });
|
[this, index]() { onControllerTypeChanged(index); });
|
||||||
ui->layout->addWidget(new QLabel(tr("Controller Type:"), ui->widget));
|
|
||||||
ui->layout->addWidget(ui->controller_type);
|
ui->layout->addWidget(ui->controller_type);
|
||||||
|
|
||||||
createPortBindingSettingsUi(index, ui, ctype);
|
createPortBindingSettingsUi(index, ui, ctype);
|
||||||
|
@ -77,13 +80,13 @@ void PortSettingsWidget::createPortBindingSettingsUi(int index, PortSettingsUI*
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
const auto buttons = Controller::GetButtonNames(ctype);
|
const auto buttons = Controller::GetButtonNames(ctype);
|
||||||
|
|
||||||
|
InputBindingWidget* first_button = nullptr;
|
||||||
|
InputBindingWidget* last_button = nullptr;
|
||||||
|
|
||||||
int start_row = 0;
|
int start_row = 0;
|
||||||
if (!buttons.empty())
|
if (!buttons.empty())
|
||||||
{
|
{
|
||||||
QFrame* line = new QFrame(container);
|
layout->addWidget(QtUtils::CreateHorizontalLine(container), start_row++, 0, 1, 4);
|
||||||
line->setFrameShape(QFrame::HLine);
|
|
||||||
line->setFrameShadow(QFrame::Sunken);
|
|
||||||
layout->addWidget(line, start_row++, 0, 1, 4);
|
|
||||||
layout->addWidget(new QLabel(tr("Button Bindings:"), container), start_row++, 0, 1, 4);
|
layout->addWidget(new QLabel(tr("Button Bindings:"), container), start_row++, 0, 1, 4);
|
||||||
|
|
||||||
const int num_rows = (static_cast<int>(buttons.size()) + 1) / 2;
|
const int num_rows = (static_cast<int>(buttons.size()) + 1) / 2;
|
||||||
|
@ -104,6 +107,12 @@ void PortSettingsWidget::createPortBindingSettingsUi(int index, PortSettingsUI*
|
||||||
layout->addWidget(label, start_row + current_row, current_column);
|
layout->addWidget(label, start_row + current_row, current_column);
|
||||||
layout->addWidget(button, start_row + current_row, current_column + 1);
|
layout->addWidget(button, start_row + current_row, current_column + 1);
|
||||||
|
|
||||||
|
if (!first_button)
|
||||||
|
first_button = button;
|
||||||
|
if (last_button)
|
||||||
|
last_button->setNextWidget(button);
|
||||||
|
last_button = button;
|
||||||
|
|
||||||
current_row++;
|
current_row++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,12 +146,62 @@ void PortSettingsWidget::createPortBindingSettingsUi(int index, PortSettingsUI*
|
||||||
layout->addWidget(label, start_row + current_row, current_column);
|
layout->addWidget(label, start_row + current_row, current_column);
|
||||||
layout->addWidget(button, start_row + current_row, current_column + 1);
|
layout->addWidget(button, start_row + current_row, current_column + 1);
|
||||||
|
|
||||||
|
if (!first_button)
|
||||||
|
first_button = button;
|
||||||
|
if (last_button)
|
||||||
|
last_button->setNextWidget(button);
|
||||||
|
last_button = button;
|
||||||
|
|
||||||
current_row++;
|
current_row++;
|
||||||
}
|
}
|
||||||
|
|
||||||
start_row += num_rows;
|
start_row += num_rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
layout->addWidget(QtUtils::CreateHorizontalLine(ui->widget), start_row++, 0, 1, 4);
|
||||||
|
|
||||||
|
if (first_button)
|
||||||
|
{
|
||||||
|
QHBoxLayout* hbox = new QHBoxLayout();
|
||||||
|
|
||||||
|
QPushButton* clear_all_button = new QPushButton(tr("Clear All"), ui->widget);
|
||||||
|
clear_all_button->connect(clear_all_button, &QPushButton::pressed, [this, first_button]() {
|
||||||
|
if (QMessageBox::question(this, tr("Clear Bindings"),
|
||||||
|
tr("Are you sure you want to clear all bound controls? This cannot be reversed.")) !=
|
||||||
|
QMessageBox::Yes)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InputBindingWidget* widget = first_button;
|
||||||
|
while (widget)
|
||||||
|
{
|
||||||
|
widget->clearBinding();
|
||||||
|
widget = widget->getNextWidget();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QPushButton* rebind_all_button = new QPushButton(tr("Rebind All"), ui->widget);
|
||||||
|
rebind_all_button->connect(rebind_all_button, &QPushButton::pressed, [this, first_button]() {
|
||||||
|
if (QMessageBox::question(this, tr("Clear Bindings"), tr("Do you want to clear all currently-bound controls?")) ==
|
||||||
|
QMessageBox::Yes)
|
||||||
|
{
|
||||||
|
InputBindingWidget* widget = first_button;
|
||||||
|
while (widget)
|
||||||
|
{
|
||||||
|
widget->clearBinding();
|
||||||
|
widget = widget->getNextWidget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
first_button->beginRebindAll();
|
||||||
|
});
|
||||||
|
|
||||||
|
hbox->addWidget(clear_all_button);
|
||||||
|
hbox->addWidget(rebind_all_button);
|
||||||
|
layout->addLayout(hbox, start_row++, 0, 1, 4, Qt::AlignRight);
|
||||||
|
}
|
||||||
|
|
||||||
if (ui->button_binding_container)
|
if (ui->button_binding_container)
|
||||||
{
|
{
|
||||||
QLayoutItem* old_item = ui->layout->replaceWidget(ui->button_binding_container, container);
|
QLayoutItem* old_item = ui->layout->replaceWidget(ui->button_binding_container, container);
|
||||||
|
|
|
@ -13,6 +13,14 @@
|
||||||
|
|
||||||
namespace QtUtils {
|
namespace QtUtils {
|
||||||
|
|
||||||
|
QFrame* CreateHorizontalLine(QWidget* parent)
|
||||||
|
{
|
||||||
|
QFrame* line = new QFrame(parent);
|
||||||
|
line->setFrameShape(QFrame::HLine);
|
||||||
|
line->setFrameShadow(QFrame::Sunken);
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
QWidget* GetRootWidget(QWidget* widget, bool stop_at_window_or_dialog)
|
QWidget* GetRootWidget(QWidget* widget, bool stop_at_window_or_dialog)
|
||||||
{
|
{
|
||||||
QWidget* next_parent = widget->parentWidget();
|
QWidget* next_parent = widget->parentWidget();
|
||||||
|
|
|
@ -6,12 +6,16 @@
|
||||||
|
|
||||||
class ByteStream;
|
class ByteStream;
|
||||||
|
|
||||||
|
class QFrame;
|
||||||
class QKeyEvent;
|
class QKeyEvent;
|
||||||
class QTableView;
|
class QTableView;
|
||||||
class QWidget;
|
class QWidget;
|
||||||
|
|
||||||
namespace QtUtils {
|
namespace QtUtils {
|
||||||
|
|
||||||
|
/// Creates a horizontal line widget.
|
||||||
|
QFrame* CreateHorizontalLine(QWidget* parent);
|
||||||
|
|
||||||
/// Returns the greatest parent of a widget, i.e. its dialog/window.
|
/// Returns the greatest parent of a widget, i.e. its dialog/window.
|
||||||
QWidget* GetRootWidget(QWidget* widget, bool stop_at_window_or_dialog = true);
|
QWidget* GetRootWidget(QWidget* widget, bool stop_at_window_or_dialog = true);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue