Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
stenzek
GitHub Repository: stenzek/duckstation
Path: blob/master/src/duckstation-qt/controllerglobalsettingswidget.cpp
4802 views
1
// SPDX-FileCopyrightText: 2019-2025 Connor McLaughlin <[email protected]>
2
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
3
4
#include "controllerglobalsettingswidget.h"
5
#include "controllerbindingwidgets.h"
6
#include "controllersettingswindow.h"
7
#include "controllersettingwidgetbinder.h"
8
#include "qtutils.h"
9
#include "settingwidgetbinder.h"
10
11
#include "fmt/format.h"
12
13
#include "util/ini_settings_interface.h"
14
#include "util/sdl_input_source.h"
15
16
#include <QtWidgets/QDialogButtonBox>
17
#include <QtWidgets/QGridLayout>
18
#include <QtWidgets/QGroupBox>
19
#include <QtWidgets/QScrollArea>
20
#include <QtWidgets/QVBoxLayout>
21
22
#include "moc_controllerglobalsettingswidget.cpp"
23
24
ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent, ControllerSettingsWindow* dialog)
25
: QWidget(parent), m_dialog(dialog)
26
{
27
m_ui.setupUi(this);
28
29
SettingsInterface* sif = dialog->getEditingSettingsInterface();
30
31
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableSDLSource, "InputSources", "SDL", true);
32
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableSDLEnhancedMode, "InputSources",
33
"SDLControllerEnhancedMode", false);
34
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableTouchPadAsPointer, "InputSources",
35
"SDLTouchpadAsPointer", false);
36
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableSDLPS5PlayerLED, "InputSources",
37
"SDLPS5PlayerLED", false);
38
connect(m_ui.enableSDLSource, &QCheckBox::checkStateChanged, this,
39
&ControllerGlobalSettingsWidget::updateSDLOptionsEnabled);
40
connect(m_ui.ledSettings, &QToolButton::clicked, this, &ControllerGlobalSettingsWidget::ledSettingsClicked);
41
connect(m_ui.SDLHelpText, &QLabel::linkActivated, this, &ControllerGlobalSettingsWidget::sdlHelpTextLinkClicked);
42
43
#ifdef _WIN32
44
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableDInputSource, "InputSources", "DInput",
45
false);
46
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableXInputSource, "InputSources", "XInput",
47
false);
48
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableRawInput, "InputSources", "RawInput",
49
false);
50
#else
51
m_ui.mainLayout->removeWidget(m_ui.xinputGroup);
52
delete m_ui.xinputGroup;
53
m_ui.xinputGroup = nullptr;
54
m_ui.mainLayout->removeWidget(m_ui.dinputGroup);
55
delete m_ui.dinputGroup;
56
m_ui.dinputGroup = nullptr;
57
#endif
58
59
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.enableMouseMapping, "UI", "EnableMouseMapping",
60
false);
61
ControllerSettingWidgetBinder::BindWidgetToInputProfileEnumSetting(
62
sif, m_ui.multitapMode, "ControllerPorts", "MultitapMode", &Settings::ParseMultitapModeName,
63
&Settings::GetMultitapModeName, &Settings::GetMultitapModeDisplayName, Settings::DEFAULT_MULTITAP_MODE,
64
MultitapMode::Count);
65
ControllerSettingWidgetBinder::BindWidgetToInputProfileFloat(sif, m_ui.pointerXScale, "ControllerPorts",
66
"PointerXScale", 8.0f);
67
ControllerSettingWidgetBinder::BindWidgetToInputProfileFloat(sif, m_ui.pointerYScale, "ControllerPorts",
68
"PointerYScale", 8.0f);
69
70
if (dialog->isEditingProfile())
71
{
72
m_ui.useProfileHotkeyBindings->setChecked(
73
m_dialog->getBoolValue("ControllerPorts", "UseProfileHotkeyBindings", false));
74
connect(m_ui.useProfileHotkeyBindings, &QCheckBox::checkStateChanged, this, [this](int new_state) {
75
m_dialog->setBoolValue("ControllerPorts", "UseProfileHotkeyBindings", (new_state == Qt::Checked));
76
emit bindingSetupChanged();
77
});
78
}
79
else
80
{
81
// remove profile options from the UI.
82
m_ui.mainLayout->removeWidget(m_ui.profileSettings);
83
delete m_ui.profileSettings;
84
m_ui.profileSettings = nullptr;
85
}
86
87
m_ui.deviceList->setModel(g_emu_thread->getInputDeviceListModel());
88
89
connect(m_ui.multitapMode, &QComboBox::currentIndexChanged, this, [this]() { emit bindingSetupChanged(); });
90
91
connect(m_ui.pointerXScale, &QSlider::valueChanged, this,
92
[this](int value) { m_ui.pointerXScaleLabel->setText(QStringLiteral("%1").arg(value)); });
93
connect(m_ui.pointerYScale, &QSlider::valueChanged, this,
94
[this](int value) { m_ui.pointerYScaleLabel->setText(QStringLiteral("%1").arg(value)); });
95
m_ui.pointerXScaleLabel->setText(QStringLiteral("%1").arg(m_ui.pointerXScale->value()));
96
m_ui.pointerYScaleLabel->setText(QStringLiteral("%1").arg(m_ui.pointerYScale->value()));
97
98
updateSDLOptionsEnabled();
99
}
100
101
ControllerGlobalSettingsWidget::~ControllerGlobalSettingsWidget() = default;
102
103
void ControllerGlobalSettingsWidget::sdlHelpTextLinkClicked(const QString& link)
104
{
105
if (link == QStringLiteral("ADVANCED_SDL_OPTIONS"))
106
{
107
ControllerCustomSettingsDialog dialog(m_dialog, m_dialog->getEditingSettingsInterface(), "InputSources",
108
SDLInputSource::GetAdvancedSettingsInfo(), "SDLInputSource",
109
tr("Advanced SDL Options"));
110
dialog.exec();
111
}
112
}
113
114
void ControllerGlobalSettingsWidget::updateSDLOptionsEnabled()
115
{
116
const bool enabled = m_ui.enableSDLSource->isChecked();
117
if (m_ui.enableSDLEnhancedMode)
118
m_ui.enableSDLEnhancedMode->setEnabled(enabled);
119
if (m_ui.enableTouchPadAsPointer)
120
m_ui.enableTouchPadAsPointer->setEnabled(enabled);
121
if (m_ui.enableSDLPS5PlayerLED)
122
m_ui.enableSDLPS5PlayerLED->setEnabled(enabled);
123
if (m_ui.ledSettings)
124
m_ui.ledSettings->setEnabled(enabled);
125
}
126
127
void ControllerGlobalSettingsWidget::ledSettingsClicked()
128
{
129
static constexpr auto config_key = [](u32 player_id, bool active) {
130
return TinyString::from_format("Player{}{}LED", player_id, active ? "Active" : "");
131
};
132
133
if (std::ranges::none_of(
134
g_emu_thread->getInputDeviceListModel()->getDeviceList(),
135
[](const InputDeviceListModel::Device& dev) { return (dev.key.source_type == InputSourceType::SDL); }))
136
{
137
QMessageBox::critical(this, tr("Error"), tr("No SDL devices are currently connected."));
138
return;
139
}
140
141
QDialog dlg(this);
142
dlg.setWindowTitle(tr("Controller LED Settings"));
143
dlg.setFixedWidth(450);
144
dlg.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
145
146
QVBoxLayout* const main_layout = new QVBoxLayout(&dlg);
147
148
QHBoxLayout* const heading_layout = new QHBoxLayout();
149
QLabel* const icon = new QLabel(&dlg);
150
icon->setPixmap(QIcon::fromTheme(QStringLiteral("lightbulb-line")).pixmap(32, 32));
151
QLabel* const heading = new QLabel(
152
tr("<strong>Controller LED Settings</strong><br>\nThe \"alternate\" color is used when analog mode is active."),
153
&dlg);
154
heading->setWordWrap(true);
155
heading_layout->addWidget(icon, 0, Qt::AlignTop | Qt::AlignLeft);
156
heading_layout->addWidget(heading, 1);
157
main_layout->addLayout(heading_layout);
158
159
QScrollArea* const scroll_area = new QScrollArea(&dlg);
160
scroll_area->setWidgetResizable(true);
161
scroll_area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
162
scroll_area->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
163
main_layout->addWidget(scroll_area, 1);
164
165
QWidget* const scroll_area_widget = new QWidget(scroll_area);
166
scroll_area->setWidget(scroll_area_widget);
167
168
QVBoxLayout* const scroll_area_layout = new QVBoxLayout(scroll_area_widget);
169
scroll_area_layout->setContentsMargins(10, 10, 10, 10);
170
171
for (const InputDeviceListModel::Device& dev : g_emu_thread->getInputDeviceListModel()->getDeviceList())
172
{
173
if (dev.key.source_type != InputSourceType::SDL)
174
continue;
175
176
QGroupBox* const gbox = new QGroupBox(QStringLiteral("%1: %2").arg(dev.identifier).arg(dev.display_name), &dlg);
177
QGridLayout* const gbox_layout = new QGridLayout(gbox);
178
for (u32 active = 0; active < 2; active++)
179
{
180
gbox_layout->addWidget(new QLabel(active ? tr("Alternate Mode:") : tr("Normal Mode:"), &dlg),
181
static_cast<int>(active), 0);
182
183
ColorPickerButton* const button = new ColorPickerButton(gbox);
184
button->setColor(SDLInputSource::ParseRGBForPlayerId(
185
m_dialog->getStringValue("SDLExtra", config_key(dev.key.source_index, active != 0), ""), dev.key.source_index,
186
active != 0));
187
gbox_layout->addWidget(button, static_cast<int>(active), 1);
188
connect(button, &ColorPickerButton::colorChanged, this,
189
[this, player_id = dev.key.source_index, active](u32 new_rgb) {
190
m_dialog->setStringValue("SDLExtra", config_key(player_id, active),
191
TinyString::from_format("{:06X}", new_rgb));
192
});
193
}
194
195
scroll_area_layout->addWidget(gbox);
196
}
197
198
scroll_area_layout->addStretch(1);
199
200
QDialogButtonBox* const bbox = new QDialogButtonBox(QDialogButtonBox::Close, &dlg);
201
connect(bbox, &QDialogButtonBox::rejected, &dlg, &QDialog::accept);
202
main_layout->addWidget(bbox);
203
204
dlg.exec();
205
}
206
207