Path: blob/master/src/duckstation-qt/controllerglobalsettingswidget.cpp
7451 views
// SPDX-FileCopyrightText: 2019-2026 Connor McLaughlin <[email protected]>1// SPDX-License-Identifier: CC-BY-NC-ND-4.023#include "controllerglobalsettingswidget.h"4#include "controllerbindingwidgets.h"5#include "controllersettingswindow.h"6#include "controllersettingwidgetbinder.h"7#include "qtutils.h"8#include "settingwidgetbinder.h"910#include "fmt/format.h"1112#include "util/ini_settings_interface.h"13#include "util/sdl_input_source.h"1415#include <QtWidgets/QDialogButtonBox>16#include <QtWidgets/QGridLayout>17#include <QtWidgets/QGroupBox>18#include <QtWidgets/QScrollArea>19#include <QtWidgets/QVBoxLayout>2021#include "moc_controllerglobalsettingswidget.cpp"2223using namespace Qt::StringLiterals;2425ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent, ControllerSettingsWindow* dialog)26: QWidget(parent), m_dialog(dialog)27{28m_ui.setupUi(this);2930SettingsInterface* sif = dialog->getEditingSettingsInterface();3132bool remove_sources = false;33if (sif)34{35// Editing game profile or input profile.36m_ui.useProfileHotkeyBindings->setChecked(sif->GetBoolValue("ControllerPorts", "UseProfileHotkeyBindings", false));37connect(m_ui.useProfileHotkeyBindings, &QCheckBox::checkStateChanged, this, [this](int new_state) {38m_dialog->setBoolValue("ControllerPorts", "UseProfileHotkeyBindings", (new_state == Qt::Checked));39emit bindingSetupChanged();40});41m_ui.useProfileInputSources->setChecked(sif->GetBoolValue("ControllerPorts", "UseProfileInputSources", false));42connect(m_ui.useProfileInputSources, &QCheckBox::checkStateChanged, this, [this](int new_state) {43m_dialog->setBoolValue("ControllerPorts", "UseProfileInputSources", (new_state == Qt::Checked));44emit bindingSetupChanged();45});46remove_sources = !m_ui.useProfileInputSources->isChecked();47}48else49{50// Editing base settings, remove profile options from the UI.51m_ui.mainLayout->removeWidget(m_ui.profileSettings);52QtUtils::SafeDeleteWidget(m_ui.profileSettings);53m_ui.profileSettingsLayout = nullptr;54m_ui.profileSettingsDescription = nullptr;55m_ui.useProfileHotkeyBindings = nullptr;56m_ui.useProfileInputSources = nullptr;57}5859if (!remove_sources)60{61ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableSDLSource, "InputSources", "SDL", true);62ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableSDLEnhancedMode, "InputSources",63"SDLControllerEnhancedMode", false);64ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableTouchPadAsPointer, "InputSources",65"SDLTouchpadAsPointer", false);66ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableSDLPS5PlayerLED, "InputSources",67"SDLPS5PlayerLED", false);68connect(m_ui.enableSDLSource, &QCheckBox::checkStateChanged, this,69&ControllerGlobalSettingsWidget::updateSDLOptionsEnabled);70connect(m_ui.ledSettings, &QToolButton::clicked, this, &ControllerGlobalSettingsWidget::ledSettingsClicked);71connect(m_ui.sdlHelpText, &QLabel::linkActivated, this, &ControllerGlobalSettingsWidget::sdlHelpTextLinkClicked);7273#ifdef _WIN3274ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableDInputSource, "InputSources", "DInput",75false);76ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableXInputSource, "InputSources", "XInput",77false);78ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableRawInput, "InputSources", "RawInput",79false);80#else81m_ui.groupsLayout->removeWidget(m_ui.xinputGroup);82QtUtils::SafeDeleteWidget(m_ui.xinputGroup);83m_ui.xinputLayout = nullptr;84m_ui.enableXInputSource = nullptr;85m_ui.xinputDescription = nullptr;86m_ui.groupsLayout->removeWidget(m_ui.dinputGroup);87QtUtils::SafeDeleteWidget(m_ui.dinputGroup);88m_ui.dinputLayout = nullptr;89m_ui.enableDInputSource = nullptr;90m_ui.dinputDescription = nullptr;91m_ui.pointerLayout->removeWidget(m_ui.enableRawInput);92m_ui.pointerLayout->removeWidget(m_ui.rawInputDescription);93QtUtils::SafeDeleteWidget(m_ui.enableRawInput);94QtUtils::SafeDeleteWidget(m_ui.rawInputDescription);95#endif9697ControllerSettingWidgetBinder::BindWidgetToInputProfileFloat(sif, m_ui.pointerXScale, "ControllerPorts",98"PointerXScale", 8.0f);99ControllerSettingWidgetBinder::BindWidgetToInputProfileFloat(sif, m_ui.pointerYScale, "ControllerPorts",100"PointerYScale", 8.0f);101102connect(m_ui.pointerXScale, &QSlider::valueChanged, this,103[this](int value) { m_ui.pointerXScaleLabel->setText(QStringLiteral("%1").arg(value)); });104connect(m_ui.pointerYScale, &QSlider::valueChanged, this,105[this](int value) { m_ui.pointerYScaleLabel->setText(QStringLiteral("%1").arg(value)); });106m_ui.pointerXScaleLabel->setText(QStringLiteral("%1").arg(m_ui.pointerXScale->value()));107m_ui.pointerYScaleLabel->setText(QStringLiteral("%1").arg(m_ui.pointerYScale->value()));108109updateSDLOptionsEnabled();110}111else112{113m_ui.groupsLayout->removeWidget(m_ui.sdlGroup);114QtUtils::SafeDeleteWidget(m_ui.sdlGroup);115m_ui.sdlGridLayout = nullptr;116m_ui.sdlLEDLayout = nullptr;117m_ui.enableSDLPS5PlayerLED = nullptr;118m_ui.ledSettings = nullptr;119m_ui.enableSDLSource = nullptr;120m_ui.enableSDLEnhancedMode = nullptr;121m_ui.sdlHelpText = nullptr;122m_ui.enableTouchPadAsPointer = nullptr;123m_ui.groupsLayout->removeWidget(m_ui.xinputGroup);124QtUtils::SafeDeleteWidget(m_ui.xinputGroup);125m_ui.xinputLayout = nullptr;126m_ui.enableXInputSource = nullptr;127m_ui.xinputDescription = nullptr;128m_ui.groupsLayout->removeWidget(m_ui.dinputGroup);129QtUtils::SafeDeleteWidget(m_ui.dinputGroup);130m_ui.dinputLayout = nullptr;131m_ui.enableDInputSource = nullptr;132m_ui.dinputDescription = nullptr;133m_ui.groupsLayout->removeWidget(m_ui.pointerGroup);134QtUtils::SafeDeleteWidget(m_ui.pointerGroup);135m_ui.pointerLayout = nullptr;136m_ui.pointerXScaleDescription = nullptr;137m_ui.pointerXScaleLayout = nullptr;138m_ui.pointerXScale = nullptr;139m_ui.pointerXScaleLabel = nullptr;140m_ui.pointerYScaleDescription = nullptr;141m_ui.pointerYScaleLayout = nullptr;142m_ui.pointerYScale = nullptr;143m_ui.pointerYScaleLabel = nullptr;144m_ui.enableRawInput = nullptr;145m_ui.rawInputDescription = nullptr;146}147148// Mapping options are only shown in global settings.149if (m_dialog->isEditingGlobalSettings())150{151ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableMouseMapping, "UI",152"EnableMouseMapping", false);153ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableSensorMapping, "UI",154"EnableSensorMapping", false);155}156else157{158QtUtils::SafeDeleteWidget(m_ui.mappingGroup);159m_ui.mappingLayout = nullptr;160m_ui.mappingDescription = nullptr;161m_ui.enableMouseMapping = nullptr;162m_ui.enableSensorMapping = nullptr;163}164165m_ui.deviceList->setModel(g_core_thread->getInputDeviceListModel());166167ControllerSettingWidgetBinder::BindWidgetToInputProfileEnumSetting(168sif, m_ui.multitapMode, "ControllerPorts", "MultitapMode", &Settings::ParseMultitapModeName,169&Settings::GetMultitapModeName, &Settings::GetMultitapModeDisplayName, Settings::DEFAULT_MULTITAP_MODE,170MultitapMode::Count);171connect(m_ui.multitapMode, &QComboBox::currentIndexChanged, this, [this]() { emit bindingSetupChanged(); });172}173174ControllerGlobalSettingsWidget::~ControllerGlobalSettingsWidget() = default;175176void ControllerGlobalSettingsWidget::sdlHelpTextLinkClicked(const QString& link)177{178if (link == "ADVANCED_SDL_OPTIONS"_L1)179{180QDialog* const dlg = new ControllerCustomSettingsDialog(m_dialog, m_dialog->getEditingSettingsInterface(),181"InputSources", SDLInputSource::GetAdvancedSettingsInfo(),182"SDLInputSource", tr("Advanced SDL Options"));183dlg->setAttribute(Qt::WA_DeleteOnClose);184dlg->open();185}186}187188void ControllerGlobalSettingsWidget::updateSDLOptionsEnabled()189{190const bool enabled = m_ui.enableSDLSource->isChecked();191if (m_ui.enableSDLEnhancedMode)192m_ui.enableSDLEnhancedMode->setEnabled(enabled);193if (m_ui.enableTouchPadAsPointer)194m_ui.enableTouchPadAsPointer->setEnabled(enabled);195if (m_ui.enableSDLPS5PlayerLED)196m_ui.enableSDLPS5PlayerLED->setEnabled(enabled);197if (m_ui.ledSettings)198m_ui.ledSettings->setEnabled(enabled);199}200201void ControllerGlobalSettingsWidget::ledSettingsClicked()202{203static constexpr auto config_key = [](u32 player_id, bool active) {204return TinyString::from_format("Player{}{}LED", player_id, active ? "Active" : "");205};206207if (std::ranges::none_of(208g_core_thread->getInputDeviceListModel()->getDeviceList(),209[](const InputDeviceListModel::Device& dev) { return (dev.key.source_type == InputSourceType::SDL); }))210{211QtUtils::AsyncMessageBox(this, QMessageBox::Critical, tr("Error"), tr("No SDL devices are currently connected."));212return;213}214215QDialog* const dlg = new QDialog(this);216dlg->setAttribute(Qt::WA_DeleteOnClose);217dlg->setWindowTitle(tr("Controller LED Settings"));218dlg->setFixedWidth(450);219dlg->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);220221QVBoxLayout* const main_layout = new QVBoxLayout(dlg);222223QHBoxLayout* const heading_layout = new QHBoxLayout;224QLabel* const icon = new QLabel;225icon->setPixmap(QIcon::fromTheme("lightbulb-line"_L1).pixmap(32));226QLabel* const heading = new QLabel(227tr("<strong>Controller LED Settings</strong><br>\nThe \"alternate\" color is used when analog mode is active."));228heading->setWordWrap(true);229heading_layout->addWidget(icon, 0, Qt::AlignTop | Qt::AlignLeft);230heading_layout->addWidget(heading, 1);231main_layout->addLayout(heading_layout);232233QScrollArea* const scroll_area = new QScrollArea(dlg);234scroll_area->setWidgetResizable(true);235scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);236scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);237main_layout->addWidget(scroll_area, 1);238239QWidget* const scroll_area_widget = new QWidget(scroll_area);240scroll_area->setWidget(scroll_area_widget);241242QVBoxLayout* const scroll_area_layout = new QVBoxLayout(scroll_area_widget);243scroll_area_layout->setContentsMargins(10, 10, 10, 10);244245for (const InputDeviceListModel::Device& dev : g_core_thread->getInputDeviceListModel()->getDeviceList())246{247if (dev.key.source_type != InputSourceType::SDL)248continue;249250QGroupBox* const gbox = new QGroupBox(QStringLiteral("%1: %2").arg(dev.identifier).arg(dev.display_name));251QGridLayout* const gbox_layout = new QGridLayout(gbox);252253for (u32 active = 0; active < 2; active++)254{255gbox_layout->addWidget(new QLabel(active ? tr("Alternate Mode:") : tr("Normal Mode:"), dlg),256static_cast<int>(active), 0);257258ColorPickerButton* const button = new ColorPickerButton(gbox);259button->setColor(SDLInputSource::ParseRGBForPlayerId(260m_dialog->getStringValue("SDLExtra", config_key(dev.key.source_index, active != 0), ""), dev.key.source_index,261active != 0));262gbox_layout->addWidget(button, static_cast<int>(active), 1);263connect(button, &ColorPickerButton::colorChanged, this,264[this, player_id = dev.key.source_index, active](u32 new_rgb) {265m_dialog->setStringValue("SDLExtra", config_key(player_id, active),266TinyString::from_format("{:06X}", new_rgb));267});268}269270scroll_area_layout->addWidget(gbox);271}272273scroll_area_layout->addStretch(1);274275QDialogButtonBox* const bbox = new QDialogButtonBox(QDialogButtonBox::Close, dlg);276bbox->button(QDialogButtonBox::Close)->setDefault(true);277connect(bbox, &QDialogButtonBox::rejected, dlg, &QDialog::accept);278main_layout->addWidget(bbox);279280dlg->open();281}282283284