diff --git a/rpcs3/pad_thread.cpp b/rpcs3/pad_thread.cpp
index 62d2e6546a..853f05c334 100644
--- a/rpcs3/pad_thread.cpp
+++ b/rpcs3/pad_thread.cpp
@@ -1,5 +1,4 @@
#include "pad_thread.h"
-#include "rpcs3qt/gamepads_settings_dialog.h"
#include "../ds4_pad_handler.h"
#ifdef _WIN32
#include "../xinput_pad_handler.h"
diff --git a/rpcs3/rpcs3.vcxproj b/rpcs3/rpcs3.vcxproj
index de4388acbd..5dfe160bbf 100644
--- a/rpcs3/rpcs3.vcxproj
+++ b/rpcs3/rpcs3.vcxproj
@@ -987,7 +987,6 @@
-
@@ -1428,7 +1427,6 @@
-
$(QTDIR)\bin\moc.exe;%(FullPath)
Moc%27ing game_compatibility.h...
diff --git a/rpcs3/rpcs3.vcxproj.filters b/rpcs3/rpcs3.vcxproj.filters
index 3f5393619c..6a44ee0c1f 100644
--- a/rpcs3/rpcs3.vcxproj.filters
+++ b/rpcs3/rpcs3.vcxproj.filters
@@ -491,9 +491,6 @@
Gui\game window
-
- Gui\settings
-
Gui\settings
@@ -688,9 +685,6 @@
Gui\game window
-
- Gui\settings
-
Gui\game list
diff --git a/rpcs3/rpcs3qt/gamepads_settings_dialog.cpp b/rpcs3/rpcs3qt/gamepads_settings_dialog.cpp
deleted file mode 100644
index 415333e4ce..0000000000
--- a/rpcs3/rpcs3qt/gamepads_settings_dialog.cpp
+++ /dev/null
@@ -1,423 +0,0 @@
-#include "gamepads_settings_dialog.h"
-#include "pad_settings_dialog.h"
-#include "qt_utils.h"
-
-#include "../Emu/Io/PadHandler.h"
-#include "../ds4_pad_handler.h"
-#ifdef _WIN32
-#include "../xinput_pad_handler.h"
-#include "../mm_joystick_handler.h"
-#elif HAVE_LIBEVDEV
-#include "../evdev_joystick_handler.h"
-#endif
-#include "../keyboard_pad_handler.h"
-#include "../Emu/Io/Null/NullPadHandler.h"
-
-#include
-#include
-#include
-#include
-#include
-
-inline std::string sstr(const QString& _in) { return _in.toStdString(); }
-constexpr auto qstr = QString::fromStdString;
-
-inline bool CreateConfigFile(const QString& dir, const QString& name)
-{
- QString input_dir = qstr(fs::get_config_dir()) + "/InputConfigs/";
- if (!QDir().mkdir(input_dir) && !QDir().exists(input_dir))
- {
- LOG_ERROR(GENERAL, "Failed to create dir %s", sstr(input_dir));
- return false;
- }
- if (!QDir().mkdir(dir) && !QDir().exists(dir))
- {
- LOG_ERROR(GENERAL, "Failed to create dir %s", sstr(dir));
- return false;
- }
-
- QString filename = dir + name + ".yml";
- QFile new_file(filename);
-
- if (!new_file.open(QIODevice::WriteOnly))
- {
- LOG_ERROR(GENERAL, "Failed to create file %s", sstr(filename));
- return false;
- }
-
- new_file.close();
- return true;
-};
-
-// taken from https://stackoverflow.com/a/30818424/8353754
-// because size policies won't work as expected (see similar bugs in Qt bugtracker)
-inline void resizeComboBoxView(QComboBox* combo)
-{
- int max_width = 0;
- QFontMetrics fm(combo->font());
- for (int i = 0; i < combo->count(); ++i)
- {
- int width = fm.width(combo->itemText(i));
- if (width > max_width) max_width = width;
- }
- if (combo->view()->minimumWidth() < max_width)
- {
- // add scrollbar width and margin
- max_width += combo->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
- max_width += combo->view()->autoScrollMargin();
- combo->view()->setMinimumWidth(max_width);
- }
-};
-
-gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
- : QDialog(parent)
-{
- setWindowTitle(tr("Gamepads Settings"));
-
- // read tooltips from json
- QFile json_file(":/Json/tooltips.json");
- json_file.open(QIODevice::ReadOnly | QIODevice::Text);
- QJsonObject json_input = QJsonDocument::fromJson(json_file.readAll()).object().value("input").toObject();
- json_file.close();
-
- QVBoxLayout *dialog_layout = new QVBoxLayout();
- QHBoxLayout *all_players = new QHBoxLayout();
-
- g_cfg_input.from_default();
- g_cfg_input.load();
-
- for (int i = 0; i < MAX_PLAYERS; i++)
- {
- QGroupBox *grp_player = new QGroupBox(QString(tr("Player %1").arg(i+1)));
-
- QVBoxLayout *ppad_layout = new QVBoxLayout();
-
- co_inputtype[i] = new QComboBox();
- co_inputtype[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
- co_inputtype[i]->view()->setTextElideMode(Qt::ElideNone);
-#ifdef WIN32
- co_inputtype[i]->setToolTip(json_input["padHandlerBox"].toString());
-#else
- co_inputtype[i]->setToolTip(json_input["padHandlerBox_Linux"].toString());
-#endif
- ppad_layout->addWidget(co_inputtype[i]);
-
- co_deviceID[i] = new QComboBox();
- co_deviceID[i]->setEnabled(false);
- co_deviceID[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
- co_deviceID[i]->view()->setTextElideMode(Qt::ElideNone);
- ppad_layout->addWidget(co_deviceID[i]);
-
- co_profile[i] = new QComboBox();
- co_profile[i]->setEnabled(false);
- co_profile[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
- co_profile[i]->view()->setTextElideMode(Qt::ElideNone);
- ppad_layout->addWidget(co_profile[i]);
-
- QHBoxLayout *button_layout = new QHBoxLayout();
- bu_new_profile[i] = new QPushButton(tr("Add Profile"));
- bu_new_profile[i]->setEnabled(false);
- bu_config[i] = new QPushButton(tr("Configure"));
- bu_config[i]->setEnabled(false);
- button_layout->setContentsMargins(0,0,0,0);
- button_layout->addWidget(bu_config[i]);
- button_layout->addWidget(bu_new_profile[i]);
- ppad_layout->addLayout(button_layout);
-
- grp_player->setLayout(ppad_layout);
- grp_player->setFixedSize(grp_player->sizeHint());
-
- // fill comboboxes after setting the groupbox's size to prevent stretch
- std::vector str_inputs = g_cfg_input.player[0]->handler.to_list();
- for (int index = 0; index < str_inputs.size(); index++)
- {
- co_inputtype[i]->addItem(qstr(str_inputs[index]));
- }
- resizeComboBoxView(co_inputtype[i]);
-
- all_players->addWidget(grp_player);
-
- if (i == 3)
- {
- dialog_layout->addLayout(all_players);
- all_players = new QHBoxLayout();
- all_players->addStretch();
- }
- }
-
- all_players->addStretch();
- dialog_layout->addLayout(all_players);
-
- QHBoxLayout *buttons_layout = new QHBoxLayout();
- QPushButton *ok_button = new QPushButton(tr("OK"));
- QPushButton *cancel_button = new QPushButton(tr("Cancel"));
- QPushButton *refresh_button = new QPushButton(tr("Refresh"));
- buttons_layout->addWidget(ok_button);
- buttons_layout->addWidget(refresh_button);
- buttons_layout->addWidget(cancel_button);
- buttons_layout->addStretch();
- dialog_layout->addLayout(buttons_layout);
-
- setLayout(dialog_layout);
- layout()->setSizeConstraint(QLayout::SetFixedSize);
-
- auto configure_combos = [=]
- {
- //Set the values from config
- for (int i = 0; i < MAX_PLAYERS; i++)
- {
- // No extra loops are necessary because setCurrentText does it for us
- co_inputtype[i]->setCurrentText(qstr(g_cfg_input.player[i]->handler.to_string()));
- // Device will be empty on some rare occasions, so fill them by force
- ChangeInputType(i);
- }
- };
-
- for (int i = 0; i < MAX_PLAYERS; i++)
- {
- connect(co_inputtype[i], &QComboBox::currentTextChanged, [=]
- {
- ChangeInputType(i);
- });
- connect(co_deviceID[i], &QComboBox::currentTextChanged, [=](const QString& dev)
- {
- std::string device = sstr(dev);
- if (!g_cfg_input.player[i]->device.from_string(device))
- {
- //Something went wrong
- LOG_ERROR(GENERAL, "Failed to convert device string: %s", device);
- return;
- }
- });
- connect(co_profile[i], &QComboBox::currentTextChanged, [=](const QString& prof)
- {
- std::string profile = sstr(prof);
- if (!g_cfg_input.player[i]->profile.from_string(profile))
- {
- //Something went wrong
- LOG_ERROR(GENERAL, "Failed to convert profile string: %s", profile);
- return;
- }
- });
- connect(bu_config[i], &QAbstractButton::clicked, [=]
- {
- ClickConfigButton(i);
- });
- connect(bu_new_profile[i], &QAbstractButton::clicked, [=]
- {
- QInputDialog* dialog = new QInputDialog(this);
- dialog->setWindowTitle(tr("Choose a unique name"));
- dialog->setLabelText(tr("Profile Name: "));
- dialog->setFixedSize(500, 100);
-
- while (dialog->exec() != QDialog::Rejected)
- {
- QString friendlyName = dialog->textValue();
- if (friendlyName == "")
- {
- QMessageBox::warning(this, tr("Error"), tr("Name cannot be empty"));
- continue;
- }
- if (friendlyName.contains("."))
- {
- QMessageBox::warning(this, tr("Error"), tr("Must choose a name without '.'"));
- continue;
- }
- if (co_profile[i]->findText(friendlyName) != -1)
- {
- QMessageBox::warning(this, tr("Error"), tr("Please choose a non-existing name"));
- continue;
- }
- if (CreateConfigFile(qstr(PadHandlerBase::get_config_dir(g_cfg_input.player[i]->handler)), friendlyName))
- {
- co_profile[i]->addItem(friendlyName);
- co_profile[i]->setCurrentText(friendlyName);
- }
- break;
- }
- });
- }
- connect(ok_button, &QPushButton::pressed, this, &gamepads_settings_dialog::SaveExit);
- connect(cancel_button, &QPushButton::pressed, this, &gamepads_settings_dialog::CancelExit);
- connect(refresh_button, &QPushButton::pressed, [=] { configure_combos(); });
-
- configure_combos();
-}
-
-void gamepads_settings_dialog::SaveExit()
-{
- //Check for invalid selection
- for (int i = 0; i < MAX_PLAYERS; i++)
- {
- if (co_deviceID[i]->currentData() == -1)
- {
- g_cfg_input.player[i]->handler.from_default();
- g_cfg_input.player[i]->device.from_default();
- g_cfg_input.player[i]->profile.from_default();
- }
- }
-
- g_cfg_input.save();
-
- QDialog::accept();
-}
-
-void gamepads_settings_dialog::CancelExit()
-{
- //Reloads config from file or defaults
- g_cfg_input.from_default();
- g_cfg_input.load();
-
- QDialog::accept();
-}
-
-std::shared_ptr gamepads_settings_dialog::GetHandler(pad_handler type)
-{
- std::shared_ptr ret_handler;
-
- switch (type)
- {
- case pad_handler::null:
- ret_handler = std::make_unique();
- break;
- case pad_handler::keyboard:
- ret_handler = std::make_unique();
- break;
- case pad_handler::ds4:
- ret_handler = std::make_unique();
- break;
-#ifdef _MSC_VER
- case pad_handler::xinput:
- ret_handler = std::make_unique();
- break;
-#endif
-#ifdef _WIN32
- case pad_handler::mm:
- ret_handler = std::make_unique();
- break;
-#endif
-#ifdef HAVE_LIBEVDEV
- case pad_handler::evdev:
- ret_handler = std::make_unique();
- break;
-#endif
- }
-
- return ret_handler;
-}
-
-void gamepads_settings_dialog::ChangeInputType(int player)
-{
- std::string handler = sstr(co_inputtype[player]->currentText());
- std::string device = g_cfg_input.player[player]->device.to_string();
- std::string profile = g_cfg_input.player[player]->profile.to_string();
-
- // Change this player's current handler
- if (!g_cfg_input.player[player]->handler.from_string(handler))
- {
- //Something went wrong
- LOG_ERROR(GENERAL, "Failed to convert input string:%s", handler);
- return;
- }
-
- // Get this player's current handler and it's currently available devices
- std::shared_ptr cur_pad_handler = GetHandler(g_cfg_input.player[player]->handler);
- std::vector list_devices = cur_pad_handler->ListDevices();
-
- // Refill the device combobox with currently available devices
- co_deviceID[player]->clear();
-
- bool force_enable = true; // enable configs even with disconnected devices
-
- switch (cur_pad_handler->m_type)
- {
-#ifdef _MSC_VER
- case pad_handler::xinput:
- {
- QString name_string = qstr(cur_pad_handler->name_string());
- for (int i = 0; i < cur_pad_handler->max_devices(); i++)
- {
- co_deviceID[player]->addItem(name_string + QString::number(i), i);
- }
- break;
- }
-#endif
- default:
- for (int i = 0; i < list_devices.size(); i++)
- {
- co_deviceID[player]->addItem(qstr(list_devices[i]), i);
- }
- force_enable = false;
- break;
- }
-
- // Handle empty device list
- bool device_found = list_devices.size() > 0;
- co_deviceID[player]->setEnabled(force_enable || device_found);
-
- if (force_enable || device_found)
- {
- co_deviceID[player]->setCurrentText(qstr(device));
- }
- else
- {
- co_deviceID[player]->addItem(tr("No Device Detected"), -1);
- }
-
- bool config_enabled = force_enable || (device_found && cur_pad_handler->has_config());
- co_profile[player]->clear();
-
- // update profile list if possible
- if (config_enabled)
- {
- QString s_profile_dir = qstr(PadHandlerBase::get_config_dir(cur_pad_handler->m_type));
- QStringList profiles = gui::utils::get_dir_entries(QDir(s_profile_dir), QStringList() << "*.yml");
-
- if (profiles.isEmpty())
- {
- QString def_name = "Default Profile";
- if (!CreateConfigFile(s_profile_dir, def_name))
- {
- config_enabled = false;
- }
- else
- {
- co_profile[player]->addItem(def_name);
- co_profile[player]->setCurrentText(def_name);
- }
- }
- else
- {
- for (const auto& prof : profiles)
- {
- co_profile[player]->addItem(prof);
- }
- co_profile[player]->setCurrentText(qstr(profile));
- }
- }
-
- if (!config_enabled)
- co_profile[player]->addItem(tr("No Profiles"));
-
- // enable configuration and profile list if possible
- bu_config[player]->setEnabled(config_enabled);
- bu_new_profile[player]->setEnabled(config_enabled);
- co_profile[player]->setEnabled(config_enabled);
-
- // update view
- resizeComboBoxView(co_deviceID[player]);
- resizeComboBoxView(co_profile[player]);
-}
-
-void gamepads_settings_dialog::ClickConfigButton(int player)
-{
- // Get this player's current handler and open its pad settings dialog
- std::shared_ptr cur_pad_handler = GetHandler(g_cfg_input.player[player]->handler);
- if (cur_pad_handler->has_config())
- {
- std::string device = sstr(co_deviceID[player]->currentText());
- std::string profile = sstr(co_profile[player]->currentText());
- pad_settings_dialog dlg(device, profile, cur_pad_handler);
- dlg.exec();
- }
-}
diff --git a/rpcs3/rpcs3qt/gamepads_settings_dialog.h b/rpcs3/rpcs3qt/gamepads_settings_dialog.h
deleted file mode 100644
index 4f43e9928c..0000000000
--- a/rpcs3/rpcs3qt/gamepads_settings_dialog.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "../Emu/System.h"
-#include "../../Utilities/Config.h"
-#include "../../Utilities/File.h"
-#include "../Emu/Io/PadHandler.h"
-
-class gamepads_settings_dialog : public QDialog
-{
- const int MAX_PLAYERS = 7;
-
-protected:
- std::shared_ptr GetHandler(pad_handler type);
- void ChangeInputType(int player);
- void ClickConfigButton(int player);
- void SaveExit();
- void CancelExit();
-
-protected:
- QComboBox *co_inputtype[7];
- QComboBox *co_deviceID[7];
- QComboBox *co_profile[7];
- QPushButton *bu_config[7];
- QPushButton *bu_new_profile[7];
-
-public:
- gamepads_settings_dialog(QWidget* parent);
- ~gamepads_settings_dialog() = default;
-};
diff --git a/rpcs3/rpcs3qt/main_window.cpp b/rpcs3/rpcs3qt/main_window.cpp
index 7c50832a38..59fdfb0f3b 100644
--- a/rpcs3/rpcs3qt/main_window.cpp
+++ b/rpcs3/rpcs3qt/main_window.cpp
@@ -29,7 +29,7 @@
#include "main_window.h"
#include "emu_settings.h"
#include "about_dialog.h"
-#include "gamepads_settings_dialog.h"
+#include "pad_settings_dialog.h"
#include "progress_dialog.h"
#include
@@ -1228,11 +1228,13 @@ void main_window::CreateConnects()
connect(ui->confIOAct, &QAction::triggered, [=]() { openSettings(3); });
connect(ui->confSystemAct, &QAction::triggered, [=]() { openSettings(4); });
- connect(ui->confPadsAct, &QAction::triggered, this, [=]
+ auto openPadSettings = [this]
{
- gamepads_settings_dialog dlg(this);
+ pad_settings_dialog dlg(this);
dlg.exec();
- });
+ };
+
+ connect(ui->confPadsAct, &QAction::triggered, openPadSettings);
connect(ui->confAutopauseManagerAct, &QAction::triggered, [=]
{
@@ -1416,7 +1418,7 @@ void main_window::CreateConnects()
}
});
- connect(ui->toolbar_controls, &QAction::triggered, [=]() { gamepads_settings_dialog dlg(this); dlg.exec(); });
+ connect(ui->toolbar_controls, &QAction::triggered, openPadSettings);
connect(ui->toolbar_config, &QAction::triggered, [=]() { openSettings(0); });
connect(ui->toolbar_list, &QAction::triggered, [=]() { ui->setlistModeListAct->trigger(); });
connect(ui->toolbar_grid, &QAction::triggered, [=]() { ui->setlistModeGridAct->trigger(); });
diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.cpp b/rpcs3/rpcs3qt/pad_settings_dialog.cpp
index 1f9eee6944..7d1fe55dd5 100644
--- a/rpcs3/rpcs3qt/pad_settings_dialog.cpp
+++ b/rpcs3/rpcs3qt/pad_settings_dialog.cpp
@@ -2,275 +2,247 @@
#include
#include
#include
-#include
-#include
-#include
#include
+#include
+#include
#include "qt_utils.h"
#include "pad_settings_dialog.h"
#include "ui_pad_settings_dialog.h"
+#include "Emu/Io/Null/NullPadHandler.h"
+
+#include "keyboard_pad_handler.h"
+#include "ds4_pad_handler.h"
+#ifdef _WIN32
+#include "xinput_pad_handler.h"
+#endif
+#ifdef _MSC_VER
+#include "mm_joystick_handler.h"
+#endif
+#ifdef HAVE_LIBEVDEV
+#include "evdev_joystick_handler.h"
+#endif
+
inline std::string sstr(const QString& _in) { return _in.toStdString(); }
constexpr auto qstr = QString::fromStdString;
-pad_settings_dialog::pad_settings_dialog(const std::string& device, const std::string& profile, std::shared_ptr handler, QWidget *parent)
- : QDialog(parent), ui(new Ui::pad_settings_dialog), m_device_name(device), m_handler(handler), m_handler_type(handler->m_type)
+inline bool CreateConfigFile(const QString& dir, const QString& name)
+{
+ QString input_dir = qstr(fs::get_config_dir()) + "/InputConfigs/";
+ if (!QDir().mkdir(input_dir) && !QDir().exists(input_dir))
+ {
+ LOG_ERROR(GENERAL, "Failed to create dir %s", sstr(input_dir));
+ return false;
+ }
+ if (!QDir().mkdir(dir) && !QDir().exists(dir))
+ {
+ LOG_ERROR(GENERAL, "Failed to create dir %s", sstr(dir));
+ return false;
+ }
+
+ QString filename = dir + name + ".yml";
+ QFile new_file(filename);
+
+ if (!new_file.open(QIODevice::WriteOnly))
+ {
+ LOG_ERROR(GENERAL, "Failed to create file %s", sstr(filename));
+ return false;
+ }
+
+ new_file.close();
+ return true;
+};
+
+pad_settings_dialog::pad_settings_dialog(QWidget *parent)
+ : QDialog(parent), ui(new Ui::pad_settings_dialog)
{
ui->setupUi(this);
- ui->b_cancel->setDefault(true);
- connect(ui->b_cancel, &QAbstractButton::clicked, this, &QWidget::close);
+ setWindowTitle(tr("Gamepads Settings"));
+ // load input config
+ g_cfg_input.from_default();
+ g_cfg_input.load();
+
+ // Create tab widget for 7 players
+ m_tabs = new QTabWidget;
+ for (int i = 1; i < 8; i++)
+ {
+ QWidget* tab = new QWidget;
+ m_tabs->addTab(tab, tr("Player %0").arg(i));
+ }
+
+ // on tab change: move the layout to the new tab and refresh
+ connect(m_tabs, &QTabWidget::currentChanged, this, &pad_settings_dialog::OnTabChanged);
+
+ // Set tab widget as layout
+ QVBoxLayout* mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(m_tabs);
+ setLayout(mainLayout);
+
+ // Fill input type combobox
+ std::vector str_inputs = g_cfg_input.player[0]->handler.to_list();
+ for (int index = 0; index < str_inputs.size(); index++)
+ {
+ ui->chooseHandler->addItem(qstr(str_inputs[index]));
+ }
+
+ // Combobox: Input type
+ connect(ui->chooseHandler, &QComboBox::currentTextChanged, this, &pad_settings_dialog::ChangeInputType);
+
+ // Combobox: Devices
+ connect(ui->chooseDevice, &QComboBox::currentTextChanged, [this](const QString& dev)
+ {
+ if (dev.isEmpty())
+ {
+ return;
+ }
+ m_device_name = sstr(dev);
+ if (!g_cfg_input.player[m_tabs->currentIndex()]->device.from_string(m_device_name))
+ {
+ // Something went wrong
+ LOG_ERROR(GENERAL, "Failed to convert device string: %s", m_device_name);
+ return;
+ }
+ });
+
+ // Combobox: Profiles
+ connect(ui->chooseProfile, &QComboBox::currentTextChanged, [this](const QString& prof)
+ {
+ if (prof.isEmpty())
+ {
+ return;
+ }
+ m_profile = sstr(prof);
+ if (!g_cfg_input.player[m_tabs->currentIndex()]->profile.from_string(m_profile))
+ {
+ // Something went wrong
+ LOG_ERROR(GENERAL, "Failed to convert profile string: %s", m_profile);
+ return;
+ }
+ ChangeProfile();
+ });
+
+ // Pushbutton: Add Profile
+ connect(ui->b_addProfile, &QAbstractButton::clicked, [=]
+ {
+ const int i = m_tabs->currentIndex();
+
+ QInputDialog* dialog = new QInputDialog(this);
+ dialog->setWindowTitle(tr("Choose a unique name"));
+ dialog->setLabelText(tr("Profile Name: "));
+ dialog->setFixedSize(500, 100);
+
+ while (dialog->exec() != QDialog::Rejected)
+ {
+ QString friendlyName = dialog->textValue();
+ if (friendlyName.isEmpty())
+ {
+ QMessageBox::warning(this, tr("Error"), tr("Name cannot be empty"));
+ continue;
+ }
+ if (friendlyName.contains("."))
+ {
+ QMessageBox::warning(this, tr("Error"), tr("Must choose a name without '.'"));
+ continue;
+ }
+ if (ui->chooseProfile->findText(friendlyName) != -1)
+ {
+ QMessageBox::warning(this, tr("Error"), tr("Please choose a non-existing name"));
+ continue;
+ }
+ if (CreateConfigFile(qstr(PadHandlerBase::get_config_dir(g_cfg_input.player[i]->handler)), friendlyName))
+ {
+ ui->chooseProfile->addItem(friendlyName);
+ ui->chooseProfile->setCurrentText(friendlyName);
+ }
+ break;
+ }
+ });
+
+ // Cancel Button
+ connect(ui->b_cancel, &QAbstractButton::clicked, this, &pad_settings_dialog::CancelExit);
+
+ // Save Button
+ connect(ui->b_ok, &QAbstractButton::clicked, this, &pad_settings_dialog::SaveExit);
+
+ // Refresh Button
+ connect(ui->b_refresh, &QPushButton::clicked, this, &pad_settings_dialog::RefreshInputTypes);
+
+ // Initialize configurable buttons
+ InitButtons();
+
+ // Set up first tab
+ OnTabChanged(0);
+
+ // repaint and resize controller image
+ ui->l_controller->setPixmap(gui::utils::get_colorized_pixmap(*ui->l_controller->pixmap(), QColor(), gui::utils::get_label_color("l_controller"), false, true));
+ ui->l_controller->setMaximumSize(ui->gb_description->sizeHint().width(), ui->l_controller->maximumHeight() * ui->gb_description->sizeHint().width() / ui->l_controller->maximumWidth());
+
+ // set tab layout constraint to the first tab
+ m_tabs->widget(0)->layout()->setSizeConstraint(QLayout::SetFixedSize);
+
+ layout()->setSizeConstraint(QLayout::SetFixedSize);
+}
+
+pad_settings_dialog::~pad_settings_dialog()
+{
+ delete ui;
+}
+
+void pad_settings_dialog::InitButtons()
+{
m_padButtons = new QButtonGroup(this);
m_palette = ui->b_left->palette(); // save normal palette
- std::string cfg_name = PadHandlerBase::get_config_dir(m_handler_type) + profile + ".yml";
-
- // Adjust to the different pad handlers
- if (m_handler_type == pad_handler::keyboard)
+ auto insertButton = [this](int id, QPushButton* button)
{
- setWindowTitle(tr("Configure Keyboard"));
- ui->b_blacklist->setEnabled(false);
- ((keyboard_pad_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
- }
- else if (m_handler_type == pad_handler::ds4)
- {
- setWindowTitle(tr("Configure DS4"));
- ((ds4_pad_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
- }
-#ifdef _MSC_VER
- else if (m_handler_type == pad_handler::xinput)
- {
- setWindowTitle(tr("Configure XInput"));
- ((xinput_pad_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
- }
-#endif
-#ifdef _WIN32
- else if (m_handler_type == pad_handler::mm)
- {
- setWindowTitle(tr("Configure MMJoystick"));
- ((mm_joystick_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
- }
-#endif
-#ifdef HAVE_LIBEVDEV
- else if (m_handler_type == pad_handler::evdev)
- {
- setWindowTitle(tr("Configure evdev"));
- ((evdev_joystick_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
- }
-#endif
-
- m_handler_cfg.load();
-
- ui->chb_vibration_large->setChecked((bool)m_handler_cfg.enable_vibration_motor_large);
- ui->chb_vibration_small->setChecked((bool)m_handler_cfg.enable_vibration_motor_small);
- ui->chb_vibration_switch->setChecked((bool)m_handler_cfg.switch_vibration_motors);
-
- // Enable Button Remapping
- if (m_handler->has_config())
- {
- // Use timer to get button input
- const auto& callback = [=](u16 val, std::string name, int preview_values[6])
- {
- if (m_handler->has_deadzones())
- {
- ui->preview_trigger_left->setValue(preview_values[0]);
- ui->preview_trigger_right->setValue(preview_values[1]);
-
- if (lx != preview_values[2] || ly != preview_values[3])
- {
- lx = preview_values[2], ly = preview_values[3];
- RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->slider_stick_left->size().width(), lx, ly);
- }
- if (rx != preview_values[4] || ry != preview_values[5])
- {
- rx = preview_values[4], ry = preview_values[5];
- RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->slider_stick_right->size().width(), rx, ry);
- }
- }
-
- if (val <= 0) return;
-
- LOG_NOTICE(HLE, "GetNextButtonPress: %s button %s pressed with value %d", m_handler_type, name, val);
- if (m_button_id > button_ids::id_pad_begin && m_button_id < button_ids::id_pad_end)
- {
- m_cfg_entries[m_button_id].key = name;
- m_cfg_entries[m_button_id].text = qstr(name);
- ReactivateButtons();
- }
- };
-
- connect(&m_timer_input, &QTimer::timeout, [=]()
- {
- std::vector buttons =
- {
- m_cfg_entries[button_ids::id_pad_l2].key,
- m_cfg_entries[button_ids::id_pad_r2].key,
- m_cfg_entries[button_ids::id_pad_lstick_left].key,
- m_cfg_entries[button_ids::id_pad_lstick_right].key,
- m_cfg_entries[button_ids::id_pad_lstick_down].key,
- m_cfg_entries[button_ids::id_pad_lstick_up].key,
- m_cfg_entries[button_ids::id_pad_rstick_left].key,
- m_cfg_entries[button_ids::id_pad_rstick_right].key,
- m_cfg_entries[button_ids::id_pad_rstick_down].key,
- m_cfg_entries[button_ids::id_pad_rstick_up].key
- };
- m_handler->GetNextButtonPress(m_device_name, callback, false, buttons);
- });
-
- m_timer_input.start(1);
- };
-
- // Enable Vibration Checkboxes
- if (m_handler->has_rumble())
- {
- const s32 min_force = m_handler->vibration_min;
- const s32 max_force = m_handler->vibration_max;
-
- ui->chb_vibration_large->setEnabled(true);
- ui->chb_vibration_small->setEnabled(true);
- ui->chb_vibration_switch->setEnabled(true);
-
- connect(ui->chb_vibration_large, &QCheckBox::clicked, [=](bool checked)
- {
- if (!checked) return;
-
- ui->chb_vibration_switch->isChecked() ? m_handler->TestVibration(m_device_name, min_force, max_force)
- : m_handler->TestVibration(m_device_name, max_force, min_force);
-
- QTimer::singleShot(300, [=]()
- {
- m_handler->TestVibration(m_device_name, min_force, min_force);
- });
- });
-
- connect(ui->chb_vibration_small, &QCheckBox::clicked, [=](bool checked)
- {
- if (!checked) return;
-
- ui->chb_vibration_switch->isChecked() ? m_handler->TestVibration(m_device_name, max_force, min_force)
- : m_handler->TestVibration(m_device_name, min_force, max_force);
-
- QTimer::singleShot(300, [=]()
- {
- m_handler->TestVibration(m_device_name, min_force, min_force);
- });
- });
-
- connect(ui->chb_vibration_switch, &QCheckBox::clicked, [=](bool checked)
- {
- checked ? m_handler->TestVibration(m_device_name, min_force, max_force)
- : m_handler->TestVibration(m_device_name, max_force, min_force);
-
- QTimer::singleShot(200, [=]()
- {
- checked ? m_handler->TestVibration(m_device_name, max_force, min_force)
- : m_handler->TestVibration(m_device_name, min_force, max_force);
-
- QTimer::singleShot(200, [=]()
- {
- m_handler->TestVibration(m_device_name, min_force, min_force);
- });
- });
- });
- }
- else
- {
- ui->verticalLayout_left->removeWidget(ui->gb_vibration);
- delete ui->gb_vibration;
- }
-
- // Enable Deadzone Settings
- if (m_handler->has_deadzones())
- {
- auto initSlider = [=](QSlider* slider, const s32& value, const s32& min, const s32& max)
- {
- slider->setEnabled(true);
- slider->setRange(min, max);
- slider->setValue(value);
- };
-
- // Enable Trigger Thresholds
- initSlider(ui->slider_trigger_left, m_handler_cfg.ltriggerthreshold, 0, m_handler->trigger_max);
- initSlider(ui->slider_trigger_right, m_handler_cfg.rtriggerthreshold, 0, m_handler->trigger_max);
- ui->preview_trigger_left->setRange(0, m_handler->trigger_max);
- ui->preview_trigger_right->setRange(0, m_handler->trigger_max);
-
- // Enable Stick Deadzones
- initSlider(ui->slider_stick_left, m_handler_cfg.lstickdeadzone, 0, m_handler->thumb_max);
- initSlider(ui->slider_stick_right, m_handler_cfg.rstickdeadzone, 0, m_handler->thumb_max);
-
- RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->slider_stick_left->size().width(), lx, ly);
- connect(ui->slider_stick_left, &QSlider::valueChanged, [&](int value)
- {
- RepaintPreviewLabel(ui->preview_stick_left, value, ui->slider_stick_left->size().width(), lx, ly);
- });
-
- RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->slider_stick_right->size().width(), rx, ry);
- connect(ui->slider_stick_right, &QSlider::valueChanged, [&](int value)
- {
- RepaintPreviewLabel(ui->preview_stick_right, value, ui->slider_stick_right->size().width(), rx, ry);
- });
- }
- else
- {
- ui->verticalLayout_right->removeWidget(ui->gb_sticks);
- ui->verticalLayout_left->removeWidget(ui->gb_triggers);
-
- delete ui->gb_sticks;
- delete ui->gb_triggers;
- }
-
- auto insertButton = [this](int id, QPushButton* button, cfg::string* cfg_name)
- {
- QString name = qstr(*cfg_name);
- m_cfg_entries.insert(std::make_pair(id, pad_button{ cfg_name, *cfg_name, name }));
m_padButtons->addButton(button, id);
- button->setText(name);
button->installEventFilter(this);
};
- insertButton(button_ids::id_pad_lstick_left, ui->b_lstick_left, &m_handler_cfg.ls_left);
- insertButton(button_ids::id_pad_lstick_down, ui->b_lstick_down, &m_handler_cfg.ls_down);
- insertButton(button_ids::id_pad_lstick_right, ui->b_lstick_right, &m_handler_cfg.ls_right);
- insertButton(button_ids::id_pad_lstick_up, ui->b_lstick_up, &m_handler_cfg.ls_up);
+ insertButton(button_ids::id_pad_lstick_left, ui->b_lstick_left);
+ insertButton(button_ids::id_pad_lstick_down, ui->b_lstick_down);
+ insertButton(button_ids::id_pad_lstick_right, ui->b_lstick_right);
+ insertButton(button_ids::id_pad_lstick_up, ui->b_lstick_up);
- insertButton(button_ids::id_pad_left, ui->b_left, &m_handler_cfg.left);
- insertButton(button_ids::id_pad_down, ui->b_down, &m_handler_cfg.down);
- insertButton(button_ids::id_pad_right, ui->b_right, &m_handler_cfg.right);
- insertButton(button_ids::id_pad_up, ui->b_up, &m_handler_cfg.up);
+ insertButton(button_ids::id_pad_left, ui->b_left);
+ insertButton(button_ids::id_pad_down, ui->b_down);
+ insertButton(button_ids::id_pad_right, ui->b_right);
+ insertButton(button_ids::id_pad_up, ui->b_up);
- insertButton(button_ids::id_pad_l1, ui->b_shift_l1, &m_handler_cfg.l1);
- insertButton(button_ids::id_pad_l2, ui->b_shift_l2, &m_handler_cfg.l2);
- insertButton(button_ids::id_pad_l3, ui->b_shift_l3, &m_handler_cfg.l3);
+ insertButton(button_ids::id_pad_l1, ui->b_shift_l1);
+ insertButton(button_ids::id_pad_l2, ui->b_shift_l2);
+ insertButton(button_ids::id_pad_l3, ui->b_shift_l3);
- insertButton(button_ids::id_pad_start, ui->b_start, &m_handler_cfg.start);
- insertButton(button_ids::id_pad_select, ui->b_select, &m_handler_cfg.select);
- insertButton(button_ids::id_pad_ps, ui->b_ps, &m_handler_cfg.ps);
+ insertButton(button_ids::id_pad_start, ui->b_start);
+ insertButton(button_ids::id_pad_select, ui->b_select);
+ insertButton(button_ids::id_pad_ps, ui->b_ps);
- insertButton(button_ids::id_pad_r1, ui->b_shift_r1, &m_handler_cfg.r1);
- insertButton(button_ids::id_pad_r2, ui->b_shift_r2, &m_handler_cfg.r2);
- insertButton(button_ids::id_pad_r3, ui->b_shift_r3, &m_handler_cfg.r3);
+ insertButton(button_ids::id_pad_r1, ui->b_shift_r1);
+ insertButton(button_ids::id_pad_r2, ui->b_shift_r2);
+ insertButton(button_ids::id_pad_r3, ui->b_shift_r3);
- insertButton(button_ids::id_pad_square, ui->b_square, &m_handler_cfg.square);
- insertButton(button_ids::id_pad_cross, ui->b_cross, &m_handler_cfg.cross);
- insertButton(button_ids::id_pad_circle, ui->b_circle, &m_handler_cfg.circle);
- insertButton(button_ids::id_pad_triangle, ui->b_triangle, &m_handler_cfg.triangle);
+ insertButton(button_ids::id_pad_square, ui->b_square);
+ insertButton(button_ids::id_pad_cross, ui->b_cross);
+ insertButton(button_ids::id_pad_circle, ui->b_circle);
+ insertButton(button_ids::id_pad_triangle, ui->b_triangle);
- insertButton(button_ids::id_pad_rstick_left, ui->b_rstick_left, &m_handler_cfg.rs_left);
- insertButton(button_ids::id_pad_rstick_down, ui->b_rstick_down, &m_handler_cfg.rs_down);
- insertButton(button_ids::id_pad_rstick_right, ui->b_rstick_right, &m_handler_cfg.rs_right);
- insertButton(button_ids::id_pad_rstick_up, ui->b_rstick_up, &m_handler_cfg.rs_up);
+ insertButton(button_ids::id_pad_rstick_left, ui->b_rstick_left);
+ insertButton(button_ids::id_pad_rstick_down, ui->b_rstick_down);
+ insertButton(button_ids::id_pad_rstick_right, ui->b_rstick_right);
+ insertButton(button_ids::id_pad_rstick_up, ui->b_rstick_up);
- m_padButtons->addButton(ui->b_reset, button_ids::id_reset_parameters);
+ m_padButtons->addButton(ui->b_reset, button_ids::id_reset_parameters);
m_padButtons->addButton(ui->b_blacklist, button_ids::id_blacklist);
- m_padButtons->addButton(ui->b_ok, button_ids::id_ok);
- m_padButtons->addButton(ui->b_cancel, button_ids::id_cancel);
+ m_padButtons->addButton(ui->b_refresh, button_ids::id_refresh);
+ m_padButtons->addButton(ui->b_ok, button_ids::id_ok);
+ m_padButtons->addButton(ui->b_cancel, button_ids::id_cancel);
connect(m_padButtons, static_cast(&QButtonGroup::buttonClicked), this, &pad_settings_dialog::OnPadButtonClicked);
- connect(&m_timer, &QTimer::timeout, [&]()
+ connect(&m_timer, &QTimer::timeout, [this]()
{
if (--m_seconds <= 0)
{
@@ -280,18 +252,191 @@ pad_settings_dialog::pad_settings_dialog(const std::string& device, const std::s
m_padButtons->button(m_button_id)->setText(tr("[ Waiting %1 ]").arg(m_seconds));
});
- UpdateLabel();
+ connect(ui->chb_vibration_large, &QCheckBox::clicked, [this](bool checked)
+ {
+ if (!checked)
+ {
+ return;
+ }
- // repaint and resize controller image
- ui->l_controller->setPixmap(gui::utils::get_colorized_pixmap(*ui->l_controller->pixmap(), QColor(), gui::utils::get_label_color("l_controller"), false, true));
- ui->l_controller->setMaximumSize(ui->gb_description->sizeHint().width(), ui->l_controller->maximumHeight() * ui->gb_description->sizeHint().width() / ui->l_controller->maximumWidth());
+ ui->chb_vibration_switch->isChecked() ? m_handler->TestVibration(m_device_name, m_min_force, m_max_force)
+ : m_handler->TestVibration(m_device_name, m_max_force, m_min_force);
- layout()->setSizeConstraint(QLayout::SetFixedSize);
+ QTimer::singleShot(300, [this]()
+ {
+ m_handler->TestVibration(m_device_name, m_min_force, m_min_force);
+ });
+ });
+
+ connect(ui->chb_vibration_small, &QCheckBox::clicked, [this](bool checked)
+ {
+ if (!checked)
+ {
+ return;
+ }
+
+ ui->chb_vibration_switch->isChecked() ? m_handler->TestVibration(m_device_name, m_max_force, m_min_force)
+ : m_handler->TestVibration(m_device_name, m_min_force, m_max_force);
+
+ QTimer::singleShot(300, [this]()
+ {
+ m_handler->TestVibration(m_device_name, m_min_force, m_min_force);
+ });
+ });
+
+ connect(ui->chb_vibration_switch, &QCheckBox::clicked, [this](bool checked)
+ {
+ checked ? m_handler->TestVibration(m_device_name, m_min_force, m_max_force)
+ : m_handler->TestVibration(m_device_name, m_max_force, m_min_force);
+
+ QTimer::singleShot(200, [this, checked]()
+ {
+ checked ? m_handler->TestVibration(m_device_name, m_max_force, m_min_force)
+ : m_handler->TestVibration(m_device_name, m_min_force, m_max_force);
+
+ QTimer::singleShot(200, [this]()
+ {
+ m_handler->TestVibration(m_device_name, m_min_force, m_min_force);
+ });
+ });
+ });
+
+ connect(ui->slider_stick_left, &QSlider::valueChanged, [&](int value)
+ {
+ RepaintPreviewLabel(ui->preview_stick_left, value, ui->slider_stick_left->size().width(), lx, ly);
+ });
+
+ connect(ui->slider_stick_right, &QSlider::valueChanged, [&](int value)
+ {
+ RepaintPreviewLabel(ui->preview_stick_right, value, ui->slider_stick_right->size().width(), rx, ry);
+ });
+
+ // Enable Button Remapping
+ const auto& callback = [=](u16 val, std::string name, int preview_values[6])
+ {
+ if (m_handler->has_deadzones())
+ {
+ ui->preview_trigger_left->setValue(preview_values[0]);
+ ui->preview_trigger_right->setValue(preview_values[1]);
+
+ if (lx != preview_values[2] || ly != preview_values[3])
+ {
+ lx = preview_values[2], ly = preview_values[3];
+ RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->slider_stick_left->size().width(), lx, ly);
+ }
+ if (rx != preview_values[4] || ry != preview_values[5])
+ {
+ rx = preview_values[4], ry = preview_values[5];
+ RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->slider_stick_right->size().width(), rx, ry);
+ }
+ }
+
+ if (val <= 0)
+ {
+ return;
+ }
+
+ LOG_NOTICE(HLE, "GetNextButtonPress: %s button %s pressed with value %d", m_handler->m_type, name, val);
+ if (m_button_id > button_ids::id_pad_begin && m_button_id < button_ids::id_pad_end)
+ {
+ m_cfg_entries[m_button_id].key = name;
+ m_cfg_entries[m_button_id].text = qstr(name);
+ ReactivateButtons();
+ }
+ };
+
+ // Use timer to get button input
+ connect(&m_timer_input, &QTimer::timeout, [this, callback]()
+ {
+ std::vector buttons =
+ {
+ m_cfg_entries[button_ids::id_pad_l2].key, m_cfg_entries[button_ids::id_pad_r2].key, m_cfg_entries[button_ids::id_pad_lstick_left].key,
+ m_cfg_entries[button_ids::id_pad_lstick_right].key, m_cfg_entries[button_ids::id_pad_lstick_down].key, m_cfg_entries[button_ids::id_pad_lstick_up].key,
+ m_cfg_entries[button_ids::id_pad_rstick_left].key, m_cfg_entries[button_ids::id_pad_rstick_right].key, m_cfg_entries[button_ids::id_pad_rstick_down].key,
+ m_cfg_entries[button_ids::id_pad_rstick_up].key
+ };
+ m_handler->GetNextButtonPress(m_device_name, callback, false, buttons);
+ });
}
-pad_settings_dialog::~pad_settings_dialog()
+void pad_settings_dialog::ReloadButtons()
{
- delete ui;
+ m_cfg_entries.clear();
+
+ auto updateButton = [this](int id, QPushButton* button, cfg::string* cfg_name)
+ {
+ const QString name = qstr(*cfg_name);
+ m_cfg_entries.insert(std::make_pair(id, pad_button{cfg_name, *cfg_name, name}));
+ button->setText(name);
+ };
+
+ updateButton(button_ids::id_pad_lstick_left, ui->b_lstick_left, &m_handler_cfg.ls_left);
+ updateButton(button_ids::id_pad_lstick_down, ui->b_lstick_down, &m_handler_cfg.ls_down);
+ updateButton(button_ids::id_pad_lstick_right, ui->b_lstick_right, &m_handler_cfg.ls_right);
+ updateButton(button_ids::id_pad_lstick_up, ui->b_lstick_up, &m_handler_cfg.ls_up);
+
+ updateButton(button_ids::id_pad_left, ui->b_left, &m_handler_cfg.left);
+ updateButton(button_ids::id_pad_down, ui->b_down, &m_handler_cfg.down);
+ updateButton(button_ids::id_pad_right, ui->b_right, &m_handler_cfg.right);
+ updateButton(button_ids::id_pad_up, ui->b_up, &m_handler_cfg.up);
+
+ updateButton(button_ids::id_pad_l1, ui->b_shift_l1, &m_handler_cfg.l1);
+ updateButton(button_ids::id_pad_l2, ui->b_shift_l2, &m_handler_cfg.l2);
+ updateButton(button_ids::id_pad_l3, ui->b_shift_l3, &m_handler_cfg.l3);
+
+ updateButton(button_ids::id_pad_start, ui->b_start, &m_handler_cfg.start);
+ updateButton(button_ids::id_pad_select, ui->b_select, &m_handler_cfg.select);
+ updateButton(button_ids::id_pad_ps, ui->b_ps, &m_handler_cfg.ps);
+
+ updateButton(button_ids::id_pad_r1, ui->b_shift_r1, &m_handler_cfg.r1);
+ updateButton(button_ids::id_pad_r2, ui->b_shift_r2, &m_handler_cfg.r2);
+ updateButton(button_ids::id_pad_r3, ui->b_shift_r3, &m_handler_cfg.r3);
+
+ updateButton(button_ids::id_pad_square, ui->b_square, &m_handler_cfg.square);
+ updateButton(button_ids::id_pad_cross, ui->b_cross, &m_handler_cfg.cross);
+ updateButton(button_ids::id_pad_circle, ui->b_circle, &m_handler_cfg.circle);
+ updateButton(button_ids::id_pad_triangle, ui->b_triangle, &m_handler_cfg.triangle);
+
+ updateButton(button_ids::id_pad_rstick_left, ui->b_rstick_left, &m_handler_cfg.rs_left);
+ updateButton(button_ids::id_pad_rstick_down, ui->b_rstick_down, &m_handler_cfg.rs_down);
+ updateButton(button_ids::id_pad_rstick_right, ui->b_rstick_right, &m_handler_cfg.rs_right);
+ updateButton(button_ids::id_pad_rstick_up, ui->b_rstick_up, &m_handler_cfg.rs_up);
+
+ // Enable Vibration Checkboxes
+ ui->gb_vibration->setEnabled(m_handler->has_rumble());
+
+ ui->chb_vibration_large->setChecked((bool)m_handler_cfg.enable_vibration_motor_large);
+ ui->chb_vibration_small->setChecked((bool)m_handler_cfg.enable_vibration_motor_small);
+ ui->chb_vibration_switch->setChecked((bool)m_handler_cfg.switch_vibration_motors);
+
+ m_min_force = m_handler->vibration_min;
+ m_max_force = m_handler->vibration_max;
+
+ // Enable Deadzone Settings
+ const bool enable_deadzones = m_handler->has_deadzones();
+
+ ui->gb_sticks->setEnabled(enable_deadzones);
+ ui->gb_triggers->setEnabled(enable_deadzones);
+
+ // Enable Trigger Thresholds
+ ui->slider_trigger_left->setRange(0, m_handler->trigger_max);
+ ui->slider_trigger_left->setValue(m_handler_cfg.ltriggerthreshold);
+
+ ui->slider_trigger_right->setRange(0, m_handler->trigger_max);
+ ui->slider_trigger_right->setValue(m_handler_cfg.rtriggerthreshold);
+
+ ui->preview_trigger_left->setRange(0, m_handler->trigger_max);
+ ui->preview_trigger_right->setRange(0, m_handler->trigger_max);
+
+ // Enable Stick Deadzones
+ ui->slider_stick_left->setRange(0, m_handler->thumb_max);
+ ui->slider_stick_left->setValue(m_handler_cfg.lstickdeadzone);
+
+ ui->slider_stick_right->setRange(0, m_handler->thumb_max);
+ ui->slider_stick_right->setValue(m_handler_cfg.rstickdeadzone);
+
+ RepaintPreviewLabel(ui->preview_stick_left, ui->slider_stick_left->value(), ui->slider_stick_left->size().width(), lx, ly);
+ RepaintPreviewLabel(ui->preview_stick_right, ui->slider_stick_right->value(), ui->slider_stick_right->size().width(), rx, ry);
}
void pad_settings_dialog::ReactivateButtons()
@@ -350,7 +495,7 @@ void pad_settings_dialog::RepaintPreviewLabel(QLabel* l, int dz, int w, int x, i
void pad_settings_dialog::keyPressEvent(QKeyEvent *keyEvent)
{
- if (m_handler_type != pad_handler::keyboard)
+ if (m_handler->m_type != pad_handler::keyboard)
{
return;
}
@@ -362,7 +507,7 @@ void pad_settings_dialog::keyPressEvent(QKeyEvent *keyEvent)
if (m_button_id <= button_ids::id_pad_begin || m_button_id >= button_ids::id_pad_end)
{
- LOG_NOTICE(HLE, "Pad Settings: Handler Type: %d, Unknown button ID: %d", static_cast(m_handler_type), m_button_id);
+ LOG_NOTICE(HLE, "Pad Settings: Handler Type: %d, Unknown button ID: %d", static_cast(m_handler->m_type), m_button_id);
}
else
{
@@ -375,7 +520,7 @@ void pad_settings_dialog::keyPressEvent(QKeyEvent *keyEvent)
void pad_settings_dialog::mousePressEvent(QMouseEvent* event)
{
- if (m_handler_type != pad_handler::keyboard)
+ if (m_handler->m_type != pad_handler::keyboard)
{
return;
}
@@ -387,7 +532,7 @@ void pad_settings_dialog::mousePressEvent(QMouseEvent* event)
if (m_button_id <= button_ids::id_pad_begin || m_button_id >= button_ids::id_pad_end)
{
- LOG_NOTICE(HLE, "Pad Settings: Handler Type: %d, Unknown button ID: %d", static_cast(m_handler_type), m_button_id);
+ LOG_NOTICE(HLE, "Pad Settings: Handler Type: %d, Unknown button ID: %d", static_cast(m_handler->m_type), m_button_id);
}
else
{
@@ -402,7 +547,9 @@ bool pad_settings_dialog::eventFilter(QObject* object, QEvent* event)
{
// Disabled buttons should not absorb mouseclicks
if (event->type() == QEvent::MouseButtonPress)
+ {
event->ignore();
+ }
return QDialog::eventFilter(object, event);
}
@@ -446,8 +593,263 @@ void pad_settings_dialog::SwitchButtons(bool is_enabled)
}
}
-void pad_settings_dialog::SaveConfig()
+void pad_settings_dialog::OnPadButtonClicked(int id)
{
+ switch (id)
+ {
+ case button_ids::id_pad_begin:
+ case button_ids::id_pad_end:
+ case button_ids::id_refresh:
+ case button_ids::id_ok:
+ case button_ids::id_cancel:
+ return;
+ case button_ids::id_reset_parameters:
+ ReactivateButtons();
+ m_handler_cfg.from_default();
+ UpdateLabel(true);
+ return;
+ case button_ids::id_blacklist:
+ m_handler->GetNextButtonPress(m_device_name, nullptr, true);
+ return;
+ default:
+ break;
+ }
+
+ for (auto but : m_padButtons->buttons())
+ {
+ but->setFocusPolicy(Qt::ClickFocus);
+ }
+
+ m_button_id = id;
+ m_padButtons->button(m_button_id)->setText(tr("[ Waiting %1 ]").arg(MAX_SECONDS));
+ m_padButtons->button(m_button_id)->setPalette(QPalette(Qt::blue));
+ SwitchButtons(false); // disable all buttons, needed for using Space, Enter and other specific buttons
+ m_timer.start(1000);
+}
+
+void pad_settings_dialog::OnTabChanged(int index)
+{
+ // Save old profile
+ SaveProfile();
+
+ // Move layout to the new tab
+ m_tabs->widget(index)->setLayout(ui->mainLayout);
+
+ // Refresh handlers
+ RefreshInputTypes();
+}
+
+std::shared_ptr pad_settings_dialog::GetHandler(pad_handler type)
+{
+ std::shared_ptr ret_handler;
+
+ switch (type)
+ {
+ case pad_handler::null:
+ ret_handler = std::make_unique();
+ break;
+ case pad_handler::keyboard:
+ ret_handler = std::make_unique();
+ break;
+ case pad_handler::ds4:
+ ret_handler = std::make_unique();
+ break;
+#ifdef _MSC_VER
+ case pad_handler::xinput:
+ ret_handler = std::make_unique();
+ break;
+#endif
+#ifdef _WIN32
+ case pad_handler::mm:
+ ret_handler = std::make_unique();
+ break;
+#endif
+#ifdef HAVE_LIBEVDEV
+ case pad_handler::evdev:
+ ret_handler = std::make_unique();
+ break;
+#endif
+ }
+
+ return ret_handler;
+}
+
+void pad_settings_dialog::ChangeInputType()
+{
+ bool force_enable = false; // enable configs even with disconnected devices
+ const int player = m_tabs->currentIndex();
+
+ const std::string handler = sstr(ui->chooseHandler->currentText());
+ const std::string device = g_cfg_input.player[player]->device.to_string();
+ const std::string profile = g_cfg_input.player[player]->profile.to_string();
+
+ // Change this player's current handler
+ if (!g_cfg_input.player[player]->handler.from_string(handler))
+ {
+ // Something went wrong
+ LOG_ERROR(GENERAL, "Failed to convert input string:%s", handler);
+ return;
+ }
+
+ ui->chooseDevice->clear();
+ ui->chooseProfile->clear();
+
+ // Get this player's current handler and it's currently available devices
+ m_handler = GetHandler(g_cfg_input.player[player]->handler);
+ const std::vector list_devices = m_handler->ListDevices();
+
+ // Refill the device combobox with currently available devices
+ switch (m_handler->m_type)
+ {
+#ifdef _MSC_VER
+ case pad_handler::xinput:
+ {
+ const QString name_string = qstr(m_handler->name_string());
+ for (int i = 0; i < m_handler->max_devices(); i++)
+ {
+ ui->chooseDevice->addItem(name_string + QString::number(i), i);
+ }
+ force_enable = true;
+ break;
+ }
+#endif
+ default:
+ {
+ for (int i = 0; i < list_devices.size(); i++)
+ {
+ ui->chooseDevice->addItem(qstr(list_devices[i]), i);
+ }
+ break;
+ }
+ }
+
+ // Handle empty device list
+ bool config_enabled = force_enable || (m_handler->m_type != pad_handler::null && list_devices.size() > 0);
+ ui->chooseDevice->setEnabled(config_enabled);
+
+ if (config_enabled)
+ {
+ ui->chooseDevice->setCurrentText(qstr(device));
+
+ QString profile_dir = qstr(PadHandlerBase::get_config_dir(m_handler->m_type));
+ QStringList profiles = gui::utils::get_dir_entries(QDir(profile_dir), QStringList() << "*.yml");
+
+ if (profiles.isEmpty())
+ {
+ QString def_name = "Default Profile";
+ if (CreateConfigFile(profile_dir, def_name))
+ {
+ ui->chooseProfile->addItem(def_name);
+ }
+ else
+ {
+ config_enabled = false;
+ }
+ }
+ else
+ {
+ for (const auto& prof : profiles)
+ {
+ ui->chooseProfile->addItem(prof);
+ }
+ ui->chooseProfile->setCurrentText(qstr(profile));
+ }
+ }
+ else
+ {
+ ui->chooseProfile->addItem(tr("No Profiles"));
+ ui->chooseDevice->addItem(tr("No Device Detected"), -1);
+ }
+
+ // enable configuration and profile list if possible
+ SwitchButtons(config_enabled);
+ ui->b_addProfile->setEnabled(config_enabled);
+ ui->chooseProfile->setEnabled(config_enabled);
+}
+
+void pad_settings_dialog::ChangeProfile()
+{
+ if (!m_handler)
+ {
+ return;
+ }
+
+ // Handle running timers
+ if (m_timer.isActive())
+ {
+ ReactivateButtons();
+ }
+ if (m_timer_input.isActive())
+ {
+ m_timer_input.stop();
+ }
+
+ // Change handler
+ const std::string cfg_name = PadHandlerBase::get_config_dir(m_handler->m_type) + m_profile + ".yml";
+
+ // Adjust to the different pad handlers
+ switch (m_handler->m_type)
+ {
+ case pad_handler::null:
+ ((NullPadHandler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
+ break;
+ case pad_handler::keyboard:
+ ui->b_blacklist->setEnabled(false);
+ ((keyboard_pad_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
+ break;
+ case pad_handler::ds4:
+ ((ds4_pad_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
+ break;
+#ifdef _MSC_VER
+ case pad_handler::xinput:
+ ((xinput_pad_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
+ break;
+#endif
+#ifdef _WIN32
+ case pad_handler::mm:
+ ((mm_joystick_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
+ break;
+#endif
+#ifdef HAVE_LIBEVDEV
+ case pad_handler::evdev:
+ ((evdev_joystick_handler*)m_handler.get())->init_config(&m_handler_cfg, cfg_name);
+ break;
+#endif
+ default:
+ break;
+ }
+
+ // Load new config
+ m_handler_cfg.load();
+
+ // Reload the buttons with the new handler and profile
+ ReloadButtons();
+
+ // Reenable input timer
+ if (ui->chooseDevice->isEnabled() && ui->chooseDevice->currentIndex() >= 0)
+ {
+ m_timer_input.start(1);
+ }
+}
+
+void pad_settings_dialog::RefreshInputTypes()
+{
+ // Set the current input type from config. Disable signal to have ChangeInputType always executed exactly once
+ ui->chooseHandler->blockSignals(true);
+ ui->chooseHandler->setCurrentText(qstr(g_cfg_input.player[m_tabs->currentIndex()]->handler.to_string()));
+ ui->chooseHandler->blockSignals(false);
+
+ // Force Change
+ ChangeInputType();
+}
+
+void pad_settings_dialog::SaveProfile()
+{
+ if (!m_handler || !ui->chooseProfile->isEnabled() || ui->chooseProfile->currentIndex() < 0)
+ {
+ return;
+ }
+
for (const auto& entry : m_cfg_entries)
{
entry.second.cfg_name->from_string(entry.second.key);
@@ -471,38 +873,30 @@ void pad_settings_dialog::SaveConfig()
m_handler_cfg.save();
}
-void pad_settings_dialog::OnPadButtonClicked(int id)
+void pad_settings_dialog::SaveExit()
{
- switch (id)
+ SaveProfile();
+
+ // Check for invalid selection
+ if (!ui->chooseDevice->isEnabled() || ui->chooseDevice->currentIndex() < 0)
{
- case button_ids::id_pad_begin:
- case button_ids::id_pad_end:
- case button_ids::id_cancel:
- return;
- case button_ids::id_reset_parameters:
- ReactivateButtons();
- m_handler_cfg.from_default();
- UpdateLabel(true);
- return;
- case button_ids::id_blacklist:
- m_handler->GetNextButtonPress(m_device_name, nullptr, true);
- return;
- case button_ids::id_ok:
- SaveConfig();
- QDialog::accept();
- return;
- default:
- break;
+ const int i = m_tabs->currentIndex();
+
+ g_cfg_input.player[i]->handler.from_default();
+ g_cfg_input.player[i]->device.from_default();
+ g_cfg_input.player[i]->profile.from_default();
}
- for (auto but : m_padButtons->buttons())
- {
- but->setFocusPolicy(Qt::ClickFocus);
- }
+ g_cfg_input.save();
- m_button_id = id;
- m_padButtons->button(m_button_id)->setText(tr("[ Waiting %1 ]").arg(MAX_SECONDS));
- m_padButtons->button(m_button_id)->setPalette(QPalette(Qt::blue));
- SwitchButtons(false); // disable all buttons, needed for using Space, Enter and other specific buttons
- m_timer.start(1000);
+ QDialog::accept();
+}
+
+void pad_settings_dialog::CancelExit()
+{
+ // Reloads config from file or defaults
+ g_cfg_input.from_default();
+ g_cfg_input.load();
+
+ QDialog::reject();
}
diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.h b/rpcs3/rpcs3qt/pad_settings_dialog.h
index 2477a3f8e6..bf95f26f45 100644
--- a/rpcs3/rpcs3qt/pad_settings_dialog.h
+++ b/rpcs3/rpcs3qt/pad_settings_dialog.h
@@ -3,27 +3,11 @@
#include
#include
#include
-#include
#include
+#include
#include
-#include "keyboard_pad_handler.h"
-#include "Utilities/types.h"
-#include "Utilities/Config.h"
#include "Emu/Io/PadHandler.h"
-#include "stdafx.h"
-#include "Emu/System.h"
-
-#ifdef _WIN32
-#include "xinput_pad_handler.h"
-#endif
-#ifdef _MSC_VER
-#include "mm_joystick_handler.h"
-#endif
-#ifdef HAVE_LIBEVDEV
-#include "evdev_joystick_handler.h"
-#endif
-#include "ds4_pad_handler.h"
namespace Ui
{
@@ -34,6 +18,8 @@ class pad_settings_dialog : public QDialog
{
Q_OBJECT
+ const int MAX_PLAYERS = 7;
+
enum button_ids
{
id_pad_begin, // begin
@@ -74,6 +60,7 @@ class pad_settings_dialog : public QDialog
id_reset_parameters,
id_blacklist,
+ id_refresh,
id_ok,
id_cancel
};
@@ -85,12 +72,26 @@ class pad_settings_dialog : public QDialog
QString text;
};
+public:
+ explicit pad_settings_dialog(QWidget *parent = nullptr);
+ ~pad_settings_dialog();
+
private Q_SLOTS:
void OnPadButtonClicked(int id);
+ void OnTabChanged(int index);
+ void RefreshInputTypes();
+ void ChangeInputType();
+ /** Save the Pad Configuration to the current Pad Handler Config File */
+ void SaveProfile();
+ void SaveExit();
+ void CancelExit();
private:
Ui::pad_settings_dialog *ui;
+ // TabWidget
+ QTabWidget* m_tabs;
+
// Button Mapping
QButtonGroup* m_padButtons;
u32 m_button_id = id_pad_begin;
@@ -102,14 +103,18 @@ private:
int rx = 0;
int ry = 0;
+ // Rumble
+ s32 m_min_force;
+ s32 m_max_force;
+
// Backup for standard button palette
QPalette m_palette;
- // Pad Handlers
- pad_handler m_handler_type;
+ // Pad Handlers
std::shared_ptr m_handler;
pad_config m_handler_cfg;
std::string m_device_name;
+ std::string m_profile;
// Remap Timer
const int MAX_SECONDS = 5;
@@ -119,27 +124,28 @@ private:
// Input timer. Its Callback handles the input
QTimer m_timer_input;
- /** Resets the view to default. Resets the Remap Timer */
- void ReactivateButtons();
-
- /** Repaints a stick deadzone preview label */
- void RepaintPreviewLabel(QLabel* l, int dz, int w, int x, int y);
-
-public:
- explicit pad_settings_dialog(const std::string& device, const std::string& profile, std::shared_ptr handler, QWidget *parent = nullptr);
- ~pad_settings_dialog();
-
- /** Handle keyboard handler input */
- void keyPressEvent(QKeyEvent *keyEvent) override;
- void mousePressEvent(QMouseEvent *event) override;
- bool eventFilter(QObject* object, QEvent* event) override;
-
/** Update all the Button Labels with current button mapping */
void UpdateLabel(bool is_reset = false);
/** Enable/Disable Buttons while trying to remap an other */
void SwitchButtons(bool is_enabled);
- /** Save the Pad Configuration to the current Pad Handler Config File */
- void SaveConfig();
+ /** Resets the view to default. Resets the Remap Timer */
+ void ReactivateButtons();
+
+ void InitButtons();
+ void ReloadButtons();
+
+ void ChangeProfile();
+
+ /** Repaints a stick deadzone preview label */
+ void RepaintPreviewLabel(QLabel* l, int dz, int w, int x, int y);
+
+ std::shared_ptr GetHandler(pad_handler type);
+
+protected:
+ /** Handle keyboard handler input */
+ void keyPressEvent(QKeyEvent *keyEvent) override;
+ void mousePressEvent(QMouseEvent *event) override;
+ bool eventFilter(QObject* object, QEvent* event) override;
};
diff --git a/rpcs3/rpcs3qt/pad_settings_dialog.ui b/rpcs3/rpcs3qt/pad_settings_dialog.ui
index fe26ee6e0f..b9ade1f0ef 100644
--- a/rpcs3/rpcs3qt/pad_settings_dialog.ui
+++ b/rpcs3/rpcs3qt/pad_settings_dialog.ui
@@ -17,867 +17,782 @@
:/rpcs3.ico:/rpcs3.ico
-
- -
-
-
- 5
-
-
-
-
-
- D-Pad
-
-
-
- 7
+
+
+
+ 60
+ 10
+ 878
+ 624
+
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
-
+
+
+ Handlers
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Up
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- W
-
-
- false
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
- -
-
-
-
-
-
- Left
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- A
-
-
- false
-
-
-
-
-
-
- -
-
-
- Right
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- D
-
-
- false
-
-
-
-
-
-
-
-
- -
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Down
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- S
-
-
- false
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
-
-
- -
-
-
- Left Analog
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Up
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- Up
-
-
- false
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
- -
-
-
-
-
-
- Left
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- Left
-
-
- false
-
-
-
-
-
-
- -
-
-
- Right
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- Right
-
-
- false
-
-
-
-
-
-
-
-
- -
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Down
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- Down
-
-
- false
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
-
-
- -
-
-
-
- 0
- 80
-
-
-
- Trigger Thresholds
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
-
-
-
- false
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- false
-
-
- Qt::Horizontal
-
-
-
-
-
- -
-
-
-
-
-
- false
-
-
- Qt::Horizontal
-
-
-
- -
-
-
- false
-
-
- Qt::Horizontal
-
-
-
-
-
-
-
-
- -
-
-
- Enable Vibration
-
-
-
- 5
-
-
- 9
-
-
- 5
-
-
- 9
-
-
-
-
-
- false
-
-
- Large
-
-
- true
-
-
-
- -
-
-
- false
-
-
- Small
-
-
- true
-
-
-
- -
-
-
- false
-
-
- Switch
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 0
-
-
-
-
- -
-
-
-
-
-
- Save
+
+
+ 5
-
- false
+
+ 5
-
-
- -
-
-
- Close
+
+ 5
+
+
+ 5
-
-
-
-
-
-
- -
-
-
- 0
-
-
-
-
-
- 0
-
-
-
-
-
-
-
- L1
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- Q
-
-
- false
-
-
-
-
-
+
-
-
-
- L2
+
+
+ Refresh
+
+
+ false
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- R
-
-
- false
-
-
-
-
-
- -
-
+
+
+ -
+
+
+ Devices
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
-
-
-
- 10
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Select
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- Space
-
-
- false
-
-
-
-
-
-
- -
-
-
- Start
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- Enter
-
-
- false
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
+
+
+
+
+
+ -
+
+
+ Profiles
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Horizontal
+
+
+ Add Profile
+
+
+ false
+
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ 5
+
+
-
+
+
+ D-Pad
+
+
+
+ 6
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+
+ 0
-
-
- 40
- 20
-
+
+ 0
-
-
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Up
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ W
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Left
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ A
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Right
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ D
+
+
+ false
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Down
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ S
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Left Analog
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Up
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ Up
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Left
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ Left
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Right
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ Right
+
+
+ false
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Down
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ Down
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 80
+
+
+
+ Trigger Thresholds
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+
+
+
+
+
+ -
+
+
+ Enable Vibration
+
+
+
+ 5
+
+
+ 9
+
+
+ 5
+
+
+ 9
+
+
-
+
+
+ Large
+
+
+ true
+
+
+
+ -
+
+
+ Small
+
+
+ true
+
+
+
+ -
+
+
+ Switch
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::MinimumExpanding
+
+
+
+ 20
+ 0
+
+
+
+
+ -
+
+
-
+
+
+ Save
+
+
+ false
+
+
+
+ -
+
+
+ Close
+
+
+ true
+
+
+
+
+
+
+
+ -
+
+
+ 0
+
+
-
+
+
+ 0
+
+
-
+
-
-
+
- PS Button
+ L1
-
+
5
@@ -891,9 +806,9 @@
5
-
-
+
- Backspace
+ Q
false
@@ -904,180 +819,1035 @@
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
- R1
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- E
-
-
- false
+
+
+ L2
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ R
+
+
+ false
+
+
+
+
-
-
- -
-
-
- R2
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
+
+ -
+
-
-
-
- T
-
-
- false
+
+
+ 10
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Select
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ Space
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Start
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ Enter
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ PS Button
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ Backspace
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
-
-
-
-
-
-
- -
-
-
-
- 0
- 200
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
+
+ -
+
+
-
+
+
+ R1
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ E
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ R2
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ T
+
+
+ false
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
- 430
- 265
+ 0
+ 200
-
-
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+
+ 430
+ 265
+
+
+
+
+
+
+ Qt::AutoText
+
+
+ :/Icons/controller.png
+
+
+ true
+
+
+ Qt::AlignBottom|Qt::AlignHCenter
+
+
+
+
+
+
+ -
+
+
+ 10
-
- Qt::AutoText
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ L3
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ F
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ R3
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ G
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
-
- :/Icons/controller.png
+
+ QSizePolicy::MinimumExpanding
-
- true
+
+
+ 20
+ 0
+
-
- Qt::AlignBottom|Qt::AlignHCenter
+
+
+ -
+
+
+ Description
+
+
-
+
+
+ Unfortunately, we currently do not natively support DualShock 3 controllers. You can however use third party tools like SCP Driver Package to allow your DualShock 3 controller to function like an XInput controller. We plan to add additional input methods in the future.
+
+
+ Qt::PlainText
+
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ true
+
+
+
+
-
-
- -
-
-
- 10
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- L3
-
-
-
- 5
+
+ -
+
+
+ 5
+
+
-
+
+
+ Face Buttons
-
- 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Triangle
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ V
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Square
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ Z
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Circle
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ C
+
+
+ false
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Cross
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ X
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Right Analog
-
- 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Up
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ PgUp
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Left
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ Home
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Right
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ End
+
+
+ false
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Down
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
+ PgDown
+
+
+ false
+
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Analog Deadzones
-
- 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
-
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+ QSizePolicy::MinimumExpanding
+
+
+
+ 20
+ 0
+
+
+
+
+ -
+
-
-
+
- F
+ Filter Noise
+
+
+ false
+
+
+
+ -
+
+
+ Restore Defaults
false
@@ -1085,673 +1855,13 @@
-
-
- -
-
-
- R3
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- G
-
-
- false
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 0
-
-
-
-
- -
-
-
- Description
-
-
-
-
-
-
- Unfortunately, we currently do not natively support DualShock 3 controllers. You can however use third party tools like SCP Driver Package to allow your DualShock 3 controller to function like an XInput controller. We plan to add additional input methods in the future.
-
-
- Qt::PlainText
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
-
-
- true
-
-
-
-
-
-
- -
-
-
- 5
-
-
-
-
-
- Face Buttons
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Triangle
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- V
-
-
- false
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
- -
-
-
-
-
-
- Square
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- Z
-
-
- false
-
-
-
-
-
-
- -
-
-
- Circle
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- C
-
-
- false
-
-
-
-
-
-
-
-
- -
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Cross
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- X
-
-
- false
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
-
-
- -
-
-
- Right Analog
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Up
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- PgUp
-
-
- false
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
- -
-
-
-
-
-
- Left
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- Home
-
-
- false
-
-
-
-
-
-
- -
-
-
- Right
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- End
-
-
- false
-
-
-
-
-
-
-
-
- -
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Down
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
- PgDown
-
-
- false
-
-
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
-
-
-
- -
-
-
- Analog Deadzones
-
-
-
- 5
-
-
- 5
-
-
- 5
-
-
- 5
-
-
-
-
-
-
-
-
- false
-
-
- Qt::Horizontal
-
-
-
- -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
- false
-
-
- Qt::Horizontal
-
-
-
- -
-
-
-
-
-
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 0
-
-
-
-
- -
-
-
-
-
-
- Filter Noise
-
-
-
- -
-
-
- Restore Defaults
-
-
- false
-
-
-
-
-
-
-
-
+
+
+
+
+