#include "gamepads_settings_dialog.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 "../Emu/System.h" input_config input_cfg; // 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")); QVBoxLayout *dialog_layout = new QVBoxLayout(); QHBoxLayout *all_players = new QHBoxLayout(); input_cfg.from_default(); input_cfg.load(); auto fill_device_combo = [](QComboBox *combo) { std::vector str_inputs = input_cfg.player_input[0].to_list(); for (int index = 0; index < str_inputs.size(); index++) { combo->addItem(str_inputs[index].c_str()); } resizeComboBoxView(combo); }; auto configure_combos = [=] { //Set the values from config for (int i = 0; i < MAX_PLAYERS; i++) { for (int j = 0; j < co_inputtype[i]->count(); j++) { if (co_inputtype[i]->itemText(j).toStdString() == input_cfg.player_input[i].to_string()) { co_inputtype[i]->setCurrentIndex(j); ChangeInputType(i); break; } } for (int j = 0; j < co_deviceID[i]->count(); j++) { if (co_deviceID[i]->itemText(j).toStdString() == input_cfg.player_device[i]->to_string()) { co_deviceID[i]->setCurrentIndex(j); ChangeDevice(i); break; } } } }; 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); 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]); QHBoxLayout *button_layout = new QHBoxLayout(); bu_config[i] = new QPushButton(tr("Config")); bu_config[i]->setEnabled(false); bu_config[i]->setFixedSize(bu_config[i]->sizeHint()); button_layout->addSpacing(bu_config[i]->sizeHint().width()*0.50f); button_layout->addWidget(bu_config[i]); button_layout->addSpacing(bu_config[i]->sizeHint().width()*0.50f); 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 fill_device_combo(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); configure_combos(); for (int i = 0; i < MAX_PLAYERS; i++) { connect(co_inputtype[i], &QComboBox::currentTextChanged, [=] { ChangeInputType(i); }); connect(co_deviceID[i], &QComboBox::currentTextChanged, [=] { ChangeDevice(i); }); connect(bu_config[i], &QAbstractButton::clicked, [=] { ClickConfigButton(i); }); } 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(); }); } void gamepads_settings_dialog::SaveExit() { //Check for invalid selection for (int i = 0; i < MAX_PLAYERS; i++) { if (co_deviceID[i]->currentData() == -1) { input_cfg.player_input[i].from_default(); input_cfg.player_device[i]->from_default(); } } input_cfg.save(); QDialog::accept(); } void gamepads_settings_dialog::CancelExit() { //Reloads config from file or defaults input_cfg.from_default(); input_cfg.load(); QDialog::accept(); } void gamepads_settings_dialog::ChangeDevice(int player) { bool success; success = input_cfg.player_device[player]->from_string(co_deviceID[player]->currentText().toStdString()); if (!success) { //Something went wrong LOG_ERROR(GENERAL, "Failed to convert device string:%s", co_deviceID[player]->currentText().toStdString().c_str()); return; } } 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) { bool success; success = input_cfg.player_input[player].from_string(co_inputtype[player]->currentText().toStdString()); if (!success) { //Something went wrong LOG_ERROR(GENERAL, "Failed to convert input string:%s", co_inputtype[player]->currentText().toStdString().c_str()); return; } std::shared_ptr cur_pad_handler = GetHandler(input_cfg.player_input[player]); std::vector list_devices = cur_pad_handler->ListDevices(); co_deviceID[player]->clear(); for (int i = 0; i < list_devices.size(); i++) co_deviceID[player]->addItem(list_devices[i].c_str(), i); if (list_devices.size() == 0) { co_deviceID[player]->addItem(tr("No Device Detected"), -1); co_deviceID[player]->setEnabled(false); } else { co_deviceID[player]->setEnabled(true); } resizeComboBoxView(co_deviceID[player]); bu_config[player]->setEnabled(cur_pad_handler->has_config()); } void gamepads_settings_dialog::ClickConfigButton(int player) { std::shared_ptr cur_pad_handler = GetHandler(input_cfg.player_input[player]); if (cur_pad_handler->has_config()) cur_pad_handler->ConfigController(*input_cfg.player_device[player]); }