1 // Copyright 2019 Dolphin Emulator Project5~5~5~
2 // Licensed under GPLv2+
3 // Refer to the license.txt file included.
4 
5 #include "DolphinQt/Config/ControllerInterface/DualShockUDPClientWidget.h"
6 
7 #include <fmt/format.h>
8 
9 #include <QBoxLayout>
10 #include <QCheckBox>
11 #include <QLabel>
12 #include <QListWidget>
13 #include <QPushButton>
14 
15 #include "Common/Config/Config.h"
16 #include "DolphinQt/Config/ControllerInterface/DualShockUDPClientAddServerDialog.h"
17 #include "InputCommon/ControllerInterface/DualShockUDPClient/DualShockUDPClient.h"
18 
DualShockUDPClientWidget()19 DualShockUDPClientWidget::DualShockUDPClientWidget()
20 {
21   CreateWidgets();
22   ConnectWidgets();
23 }
24 
CreateWidgets()25 void DualShockUDPClientWidget::CreateWidgets()
26 {
27   auto* main_layout = new QVBoxLayout;
28 
29   m_servers_enabled = new QCheckBox(tr("Enable"));
30   m_servers_enabled->setChecked(Config::Get(ciface::DualShockUDPClient::Settings::SERVERS_ENABLED));
31   main_layout->addWidget(m_servers_enabled, 0, {});
32 
33   m_server_list = new QListWidget();
34   main_layout->addWidget(m_server_list);
35 
36   m_add_server = new QPushButton(tr("Add..."));
37   m_add_server->setEnabled(m_servers_enabled->isChecked());
38 
39   m_remove_server = new QPushButton(tr("Remove"));
40   m_remove_server->setEnabled(m_servers_enabled->isChecked());
41 
42   QHBoxLayout* hlayout = new QHBoxLayout;
43   hlayout->addStretch();
44   hlayout->addWidget(m_add_server);
45   hlayout->addWidget(m_remove_server);
46 
47   main_layout->addItem(hlayout);
48 
49   auto* description =
50       new QLabel(tr("DSU protocol enables the use of input and motion data from compatible "
51                     "sources, like PlayStation, Nintendo Switch and Steam controllers.<br><br>"
52                     "For setup instructions, "
53                     "<a href=\"https://wiki.dolphin-emu.org/index.php?title=DSU_Client\">"
54                     "refer to this page</a>."));
55   description->setTextFormat(Qt::RichText);
56   description->setWordWrap(true);
57   description->setTextInteractionFlags(Qt::TextBrowserInteraction);
58   description->setOpenExternalLinks(true);
59   main_layout->addWidget(description);
60 
61   setLayout(main_layout);
62 
63   RefreshServerList();
64 }
65 
ConnectWidgets()66 void DualShockUDPClientWidget::ConnectWidgets()
67 {
68   connect(m_servers_enabled, &QCheckBox::clicked, this,
69           &DualShockUDPClientWidget::OnServersToggled);
70   connect(m_add_server, &QPushButton::clicked, this, &DualShockUDPClientWidget::OnServerAdded);
71   connect(m_remove_server, &QPushButton::clicked, this, &DualShockUDPClientWidget::OnServerRemoved);
72 }
73 
RefreshServerList()74 void DualShockUDPClientWidget::RefreshServerList()
75 {
76   m_server_list->clear();
77 
78   const auto server_address_setting =
79       Config::Get(ciface::DualShockUDPClient::Settings::SERVER_ADDRESS);
80   const auto server_port_setting = Config::Get(ciface::DualShockUDPClient::Settings::SERVER_PORT);
81 
82   // Update our servers setting if the user is using old configuration
83   if (!server_address_setting.empty() && server_port_setting != 0)
84   {
85     const auto& servers_setting = Config::Get(ciface::DualShockUDPClient::Settings::SERVERS);
86     Config::SetBaseOrCurrent(ciface::DualShockUDPClient::Settings::SERVERS,
87                              servers_setting + fmt::format("{}:{}:{};", "DS4",
88                                                            server_address_setting,
89                                                            server_port_setting));
90     Config::SetBase(ciface::DualShockUDPClient::Settings::SERVER_ADDRESS, "");
91     Config::SetBase(ciface::DualShockUDPClient::Settings::SERVER_PORT, 0);
92   }
93 
94   const auto& servers_setting = Config::Get(ciface::DualShockUDPClient::Settings::SERVERS);
95   const auto server_details = SplitString(servers_setting, ';');
96   for (const std::string& server_detail : server_details)
97   {
98     const auto server_info = SplitString(server_detail, ':');
99     if (server_info.size() < 3)
100       continue;
101 
102     QListWidgetItem* list_item = new QListWidgetItem(QString::fromStdString(
103         fmt::format("{}:{} - {}", server_info[1], server_info[2], server_info[0])));
104     m_server_list->addItem(list_item);
105   }
106   emit ConfigChanged();
107 }
108 
OnServerAdded()109 void DualShockUDPClientWidget::OnServerAdded()
110 {
111   DualShockUDPClientAddServerDialog add_server_dialog(this);
112   connect(&add_server_dialog, &DualShockUDPClientAddServerDialog::accepted, this,
113           &DualShockUDPClientWidget::RefreshServerList);
114   add_server_dialog.exec();
115 }
116 
OnServerRemoved()117 void DualShockUDPClientWidget::OnServerRemoved()
118 {
119   const int row_to_remove = m_server_list->currentRow();
120 
121   const auto& servers_setting = Config::Get(ciface::DualShockUDPClient::Settings::SERVERS);
122   const auto server_details = SplitString(servers_setting, ';');
123 
124   std::string new_server_setting;
125   for (int i = 0; i < m_server_list->count(); i++)
126   {
127     if (i == row_to_remove)
128     {
129       continue;
130     }
131 
132     new_server_setting += server_details[i] + ';';
133   }
134 
135   Config::SetBaseOrCurrent(ciface::DualShockUDPClient::Settings::SERVERS, new_server_setting);
136 
137   RefreshServerList();
138 }
139 
OnServersToggled()140 void DualShockUDPClientWidget::OnServersToggled()
141 {
142   bool checked = m_servers_enabled->isChecked();
143   Config::SetBaseOrCurrent(ciface::DualShockUDPClient::Settings::SERVERS_ENABLED, checked);
144   m_add_server->setEnabled(checked);
145   m_remove_server->setEnabled(checked);
146 }
147