1
0
Fork 0
forked from suyu/suyu

configuration: add option to select network interface

This commit renames the "Services" tab to "Network" and adds a combobox that allows the user to select the network interface that yuzu should use. This new setting is now used to get the local IP address in Network::GetHostIPv4Address. This prevents yuzu from selecting the wrong network interface and thus using the wrong IP address. The return type of Network::GetHostIPv4Adress has also been changed.
This commit is contained in:
spholz 2021-08-12 21:32:53 +02:00
parent 33ebe471e8
commit 1e98e73828
16 changed files with 279 additions and 91 deletions

View file

@ -701,7 +701,7 @@ if (APPLE)
elseif (WIN32) elseif (WIN32)
# WSAPoll and SHGetKnownFolderPath (AppData/Roaming) didn't exist before WinNT 6.x (Vista) # WSAPoll and SHGetKnownFolderPath (AppData/Roaming) didn't exist before WinNT 6.x (Vista)
add_definitions(-D_WIN32_WINNT=0x0600 -DWINVER=0x0600) add_definitions(-D_WIN32_WINNT=0x0600 -DWINVER=0x0600)
set(PLATFORM_LIBRARIES winmm ws2_32) set(PLATFORM_LIBRARIES winmm ws2_32 iphlpapi)
if (MINGW) if (MINGW)
# PSAPI is the Process Status API # PSAPI is the Process Status API
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version) set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version)

View file

@ -433,9 +433,10 @@ struct Values {
BasicSetting<std::string> log_filter{"*:Info", "log_filter"}; BasicSetting<std::string> log_filter{"*:Info", "log_filter"};
BasicSetting<bool> use_dev_keys{false, "use_dev_keys"}; BasicSetting<bool> use_dev_keys{false, "use_dev_keys"};
// Services // Network
BasicSetting<std::string> bcat_backend{"none", "bcat_backend"}; BasicSetting<std::string> bcat_backend{"none", "bcat_backend"};
BasicSetting<bool> bcat_boxcat_local{false, "bcat_boxcat_local"}; BasicSetting<bool> bcat_boxcat_local{false, "bcat_boxcat_local"};
BasicSetting<std::string> network_interface{std::string(), "network_interface"};
// WebService // WebService
BasicSetting<bool> enable_telemetry{true, "enable_telemetry"}; BasicSetting<bool> enable_telemetry{true, "enable_telemetry"};

View file

@ -636,6 +636,8 @@ add_library(core STATIC
memory.h memory.h
network/network.cpp network/network.cpp
network/network.h network/network.h
network/network_interface.cpp
network/network_interface.h
network/sockets.h network/sockets.h
perf_stats.cpp perf_stats.cpp
perf_stats.h perf_stats.h

View file

@ -179,10 +179,10 @@ private:
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
if (Settings::values.bcat_backend.GetValue() == "none") { if (Network::GetHostIPv4Address().has_value()) {
rb.PushEnum(RequestState::NotSubmitted);
} else {
rb.PushEnum(RequestState::Connected); rb.PushEnum(RequestState::Connected);
} else {
rb.PushEnum(RequestState::NotSubmitted);
} }
} }
@ -322,12 +322,15 @@ private:
void GetCurrentIpAddress(Kernel::HLERequestContext& ctx) { void GetCurrentIpAddress(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service_NIFM, "(STUBBED) called"); LOG_WARNING(Service_NIFM, "(STUBBED) called");
const auto [ipv4, error] = Network::GetHostIPv4Address(); auto ipv4 = Network::GetHostIPv4Address();
UNIMPLEMENTED_IF(error != Network::Errno::SUCCESS); if (!ipv4) {
LOG_CRITICAL(Service_NIFM, "Couldn't get host IPv4 address, defaulting to 0.0.0.0");
ipv4.emplace(Network::IPv4Address{0, 0, 0, 0});
}
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushRaw(ipv4); rb.PushRaw(ipv4.value());
} }
void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) { void CreateTemporaryNetworkProfile(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_NIFM, "called"); LOG_DEBUG(Service_NIFM, "called");
@ -354,13 +357,16 @@ private:
static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting), static_assert(sizeof(IpConfigInfo) == sizeof(IpAddressSetting) + sizeof(DnsSetting),
"IpConfigInfo has incorrect size."); "IpConfigInfo has incorrect size.");
const auto [ipv4, error] = Network::GetHostIPv4Address(); auto ipv4 = Network::GetHostIPv4Address();
ASSERT_MSG(error == Network::Errno::SUCCESS, "Couldn't get host IPv4 address"); if (!ipv4) {
LOG_CRITICAL(Service_NIFM, "Couldn't get host IPv4 address, defaulting to 0.0.0.0");
ipv4.emplace(Network::IPv4Address{0, 0, 0, 0});
}
const IpConfigInfo ip_config_info{ const IpConfigInfo ip_config_info{
.ip_address_setting{ .ip_address_setting{
.is_automatic{true}, .is_automatic{true},
.current_address{ipv4}, .current_address{ipv4.value()},
.subnet_mask{255, 255, 255, 0}, .subnet_mask{255, 255, 255, 0},
.gateway{192, 168, 1, 1}, .gateway{192, 168, 1, 1},
}, },
@ -387,10 +393,10 @@ private:
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
if (Settings::values.bcat_backend.GetValue() == "none") { if (Network::GetHostIPv4Address().has_value()) {
rb.Push<u8>(0);
} else {
rb.Push<u8>(1); rb.Push<u8>(1);
} else {
rb.Push<u8>(0);
} }
} }
void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) { void IsAnyInternetRequestAccepted(Kernel::HLERequestContext& ctx) {
@ -398,10 +404,10 @@ private:
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
if (Settings::values.bcat_backend.GetValue() == "none") { if (Network::GetHostIPv4Address().has_value()) {
rb.Push<u8>(0);
} else {
rb.Push<u8>(1); rb.Push<u8>(1);
} else {
rb.Push<u8>(0);
} }
} }
}; };

View file

@ -10,8 +10,8 @@
#include "common/common_funcs.h" #include "common/common_funcs.h"
#ifdef _WIN32 #ifdef _WIN32
#define _WINSOCK_DEPRECATED_NO_WARNINGS // gethostname
#include <winsock2.h> #include <winsock2.h>
#include <ws2tcpip.h>
#elif YUZU_UNIX #elif YUZU_UNIX
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
@ -19,6 +19,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <poll.h> #include <poll.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h> #include <unistd.h>
#else #else
#error "Unimplemented platform" #error "Unimplemented platform"
@ -27,7 +28,9 @@
#include "common/assert.h" #include "common/assert.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/settings.h"
#include "core/network/network.h" #include "core/network/network.h"
#include "core/network/network_interface.h"
#include "core/network/sockets.h" #include "core/network/sockets.h"
namespace Network { namespace Network {
@ -357,27 +360,27 @@ NetworkInstance::~NetworkInstance() {
Finalize(); Finalize();
} }
std::pair<IPv4Address, Errno> GetHostIPv4Address() { std::optional<IPv4Address> GetHostIPv4Address() {
std::array<char, 256> name{}; const std::string& selected_network_interface = Settings::values.network_interface.GetValue();
if (gethostname(name.data(), static_cast<int>(name.size()) - 1) == SOCKET_ERROR) { const auto network_interfaces = Network::GetAvailableNetworkInterfaces();
return {IPv4Address{}, GetAndLogLastError()}; ASSERT_MSG(network_interfaces.size() > 0, "GetAvailableNetworkInterfaces returned no interfaces");
}
hostent* const ent = gethostbyname(name.data());
if (!ent) {
return {IPv4Address{}, GetAndLogLastError()};
}
if (ent->h_addr_list == nullptr) {
UNIMPLEMENTED_MSG("No addr provided in hostent->h_addr_list");
return {IPv4Address{}, Errno::SUCCESS};
}
if (ent->h_length != sizeof(in_addr)) {
UNIMPLEMENTED_MSG("Unexpected size={} in hostent->h_length", ent->h_length);
}
in_addr addr; const auto res = std::ranges::find_if(network_interfaces,
std::memcpy(&addr, ent->h_addr_list[0], sizeof(addr)); [&selected_network_interface](const auto& interface) {
return {TranslateIPv4(addr), Errno::SUCCESS}; return interface.name == selected_network_interface;
});
if (res != network_interfaces.end()) {
char ip_addr[16];
ASSERT(inet_ntop(AF_INET, &res->ip_address, ip_addr, sizeof(ip_addr)) != nullptr);
LOG_INFO(Network, "IP address: {}", ip_addr);
return TranslateIPv4(res->ip_address);
} else {
LOG_ERROR(Network, "Couldn't find selected interface \"{}\"", selected_network_interface);
return {};
}
} }
std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) { std::pair<s32, Errno> Poll(std::vector<PollFD>& pollfds, s32 timeout) {

View file

@ -5,6 +5,7 @@
#pragma once #pragma once
#include <array> #include <array>
#include <optional>
#include <utility> #include <utility>
#include "common/common_funcs.h" #include "common/common_funcs.h"
@ -93,7 +94,7 @@ public:
}; };
/// @brief Returns host's IPv4 address /// @brief Returns host's IPv4 address
/// @return Pair of an array of human ordered IPv4 address (e.g. 192.168.0.1) and an error code /// @return human ordered IPv4 address (e.g. 192.168.0.1) as an array
std::pair<IPv4Address, Errno> GetHostIPv4Address(); std::optional<IPv4Address> GetHostIPv4Address();
} // namespace Network } // namespace Network

View file

@ -0,0 +1,113 @@
// Copyright 2021 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <vector>
#include "common/common_types.h"
#include "common/logging/log.h"
#include "common/string_util.h"
#include "core/network/network_interface.h"
#ifdef _WIN32
#include <iphlpapi.h>
#else
#include <ifaddrs.h>
#include <net/if.h>
#include <cerrno>
#endif
namespace Network {
#ifdef _WIN32
std::vector<NetworkInterface> GetAvailableNetworkInterfaces() {
std::vector<NetworkInterface> result;
std::vector<u8> adapter_addresses_raw;
auto adapter_addresses = reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_addresses_raw.data());
DWORD ret = ERROR_BUFFER_OVERFLOW;
DWORD buf_size = 0;
// retry up to 5 times
for (int i = 0; i < 5 && ret == ERROR_BUFFER_OVERFLOW; i++) {
ret = GetAdaptersAddresses(AF_INET, GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER,
nullptr, adapter_addresses, &buf_size);
if (ret == ERROR_BUFFER_OVERFLOW) {
adapter_addresses_raw.resize(buf_size);
adapter_addresses =
reinterpret_cast<PIP_ADAPTER_ADDRESSES>(adapter_addresses_raw.data());
} else {
break;
}
}
if (ret == NO_ERROR) {
for (auto current_address = adapter_addresses; current_address != nullptr;
current_address = current_address->Next) {
if (current_address->FirstUnicastAddress == nullptr ||
current_address->FirstUnicastAddress->Address.lpSockaddr == nullptr) {
continue;
}
if (current_address->OperStatus != IfOperStatusUp) {
continue;
}
const auto ip_addr = std::bit_cast<struct sockaddr_in>(
*current_address->FirstUnicastAddress->Address.lpSockaddr)
.sin_addr;
result.push_back(NetworkInterface{
.name{Common::UTF16ToUTF8(std::wstring{current_address->FriendlyName})},
.ip_address{ip_addr}
});
}
} else {
LOG_ERROR(Network, "Failed to get network interfaces with GetAdaptersAddresses");
}
return result;
}
#else
std::vector<NetworkInterface> GetAvailableNetworkInterfaces() {
std::vector<NetworkInterface> result;
struct ifaddrs* ifaddr = nullptr;
if (getifaddrs(&ifaddr) != 0) {
LOG_ERROR(Network, "Failed to get network interfaces with getifaddrs: {}",
std::strerror(errno));
return result;
}
for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == nullptr) {
continue;
}
if (ifa->ifa_addr->sa_family != AF_INET) {
continue;
}
if (!(ifa->ifa_flags & IFF_UP) || ifa->ifa_flags & IFF_LOOPBACK) {
continue;
}
result.push_back(NetworkInterface{
.name{ifa->ifa_name},
.ip_address{std::bit_cast<struct sockaddr_in>(*ifa->ifa_addr).sin_addr}
});
}
freeifaddrs(ifaddr);
return result;
}
#endif
} // namespace Network

View file

@ -0,0 +1,25 @@
// Copyright 2021 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <vector>
#ifdef _WIN32
#include <winsock2.h>
#else
#include <netinet/in.h>
#endif
namespace Network {
struct NetworkInterface {
std::string name;
struct in_addr ip_address;
};
std::vector<NetworkInterface> GetAvailableNetworkInterfaces();
} // namespace Network

View file

@ -102,9 +102,9 @@ add_executable(yuzu
configuration/configure_profile_manager.cpp configuration/configure_profile_manager.cpp
configuration/configure_profile_manager.h configuration/configure_profile_manager.h
configuration/configure_profile_manager.ui configuration/configure_profile_manager.ui
configuration/configure_service.cpp configuration/configure_network.cpp
configuration/configure_service.h configuration/configure_network.h
configuration/configure_service.ui configuration/configure_network.ui
configuration/configure_system.cpp configuration/configure_system.cpp
configuration/configure_system.h configuration/configure_system.h
configuration/configure_system.ui configuration/configure_system.ui

View file

@ -692,6 +692,7 @@ void Config::ReadServiceValues() {
qt_config->beginGroup(QStringLiteral("Services")); qt_config->beginGroup(QStringLiteral("Services"));
ReadBasicSetting(Settings::values.bcat_backend); ReadBasicSetting(Settings::values.bcat_backend);
ReadBasicSetting(Settings::values.bcat_boxcat_local); ReadBasicSetting(Settings::values.bcat_boxcat_local);
ReadBasicSetting(Settings::values.network_interface);
qt_config->endGroup(); qt_config->endGroup();
} }
@ -1144,7 +1145,7 @@ void Config::SaveValues() {
SaveDataStorageValues(); SaveDataStorageValues();
SaveDebuggingValues(); SaveDebuggingValues();
SaveDisabledAddOnValues(); SaveDisabledAddOnValues();
SaveServiceValues(); SaveNetworkValues();
SaveUIValues(); SaveUIValues();
SaveWebServiceValues(); SaveWebServiceValues();
SaveMiscellaneousValues(); SaveMiscellaneousValues();
@ -1238,11 +1239,12 @@ void Config::SaveDebuggingValues() {
qt_config->endGroup(); qt_config->endGroup();
} }
void Config::SaveServiceValues() { void Config::SaveNetworkValues() {
qt_config->beginGroup(QStringLiteral("Services")); qt_config->beginGroup(QStringLiteral("Services"));
WriteBasicSetting(Settings::values.bcat_backend); WriteBasicSetting(Settings::values.bcat_backend);
WriteBasicSetting(Settings::values.bcat_boxcat_local); WriteBasicSetting(Settings::values.bcat_boxcat_local);
WriteBasicSetting(Settings::values.network_interface);
qt_config->endGroup(); qt_config->endGroup();
} }

View file

@ -88,7 +88,7 @@ private:
void SaveCoreValues(); void SaveCoreValues();
void SaveDataStorageValues(); void SaveDataStorageValues();
void SaveDebuggingValues(); void SaveDebuggingValues();
void SaveServiceValues(); void SaveNetworkValues();
void SaveDisabledAddOnValues(); void SaveDisabledAddOnValues();
void SaveMiscellaneousValues(); void SaveMiscellaneousValues();
void SavePathValues(); void SavePathValues();

View file

@ -147,12 +147,12 @@
<string>Web</string> <string>Web</string>
</attribute> </attribute>
</widget> </widget>
<widget class="ConfigureService" name="serviceTab"> <widget class="ConfigureNetwork" name="networkTab">
<property name="accessibleName"> <property name="accessibleName">
<string>Services</string> <string>Network</string>
</property> </property>
<attribute name="title"> <attribute name="title">
<string>Services</string> <string>Network</string>
</attribute> </attribute>
</widget> </widget>
</widget> </widget>
@ -242,9 +242,9 @@
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget> <customwidget>
<class>ConfigureService</class> <class>ConfigureNetwork</class>
<extends>QWidget</extends> <extends>QWidget</extends>
<header>configuration/configure_service.h</header> <header>configuration/configure_network.h</header>
<container>1</container> <container>1</container>
</customwidget> </customwidget>
<customwidget> <customwidget>

View file

@ -67,7 +67,7 @@ void ConfigureDialog::ApplyConfiguration() {
ui->audioTab->ApplyConfiguration(); ui->audioTab->ApplyConfiguration();
ui->debugTab->ApplyConfiguration(); ui->debugTab->ApplyConfiguration();
ui->webTab->ApplyConfiguration(); ui->webTab->ApplyConfiguration();
ui->serviceTab->ApplyConfiguration(); ui->networkTab->ApplyConfiguration();
Core::System::GetInstance().ApplySettings(); Core::System::GetInstance().ApplySettings();
Settings::LogSettings(); Settings::LogSettings();
} }
@ -103,7 +103,7 @@ Q_DECLARE_METATYPE(QList<QWidget*>);
void ConfigureDialog::PopulateSelectionList() { void ConfigureDialog::PopulateSelectionList() {
const std::array<std::pair<QString, QList<QWidget*>>, 6> items{ const std::array<std::pair<QString, QList<QWidget*>>, 6> items{
{{tr("General"), {ui->generalTab, ui->hotkeysTab, ui->uiTab, ui->webTab, ui->debugTab}}, {{tr("General"), {ui->generalTab, ui->hotkeysTab, ui->uiTab, ui->webTab, ui->debugTab}},
{tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}}, {tr("System"), {ui->systemTab, ui->profileManagerTab, ui->networkTab, ui->filesystemTab}},
{tr("CPU"), {ui->cpuTab}}, {tr("CPU"), {ui->cpuTab}},
{tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}}, {tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}},
{tr("Audio"), {ui->audioTab}}, {tr("Audio"), {ui->audioTab}},

View file

@ -5,9 +5,10 @@
#include <QGraphicsItem> #include <QGraphicsItem>
#include <QtConcurrent/QtConcurrent> #include <QtConcurrent/QtConcurrent>
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h"
#include "core/hle/service/bcat/backend/boxcat.h" #include "core/hle/service/bcat/backend/boxcat.h"
#include "ui_configure_service.h" #include "ui_configure_network.h"
#include "yuzu/configuration/configure_service.h" #include "yuzu/configuration/configure_network.h"
#ifdef YUZU_ENABLE_BOXCAT #ifdef YUZU_ENABLE_BOXCAT
namespace { namespace {
@ -35,8 +36,8 @@ QString FormatEventStatusString(const Service::BCAT::EventStatus& status) {
} // Anonymous namespace } // Anonymous namespace
#endif #endif
ConfigureService::ConfigureService(QWidget* parent) ConfigureNetwork::ConfigureNetwork(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureService>()) { : QWidget(parent), ui(std::make_unique<Ui::ConfigureNetwork>()) {
ui->setupUi(this); ui->setupUi(this);
ui->bcat_source->addItem(QStringLiteral("None")); ui->bcat_source->addItem(QStringLiteral("None"));
@ -47,29 +48,42 @@ ConfigureService::ConfigureService(QWidget* parent)
ui->bcat_source->addItem(QStringLiteral("Boxcat"), QStringLiteral("boxcat")); ui->bcat_source->addItem(QStringLiteral("Boxcat"), QStringLiteral("boxcat"));
#endif #endif
ui->network_interface->addItem(QStringLiteral("None"));
for (const auto& interface : Network::GetAvailableNetworkInterfaces()) {
ui->network_interface->addItem(QString::fromStdString(interface.name));
}
connect(ui->bcat_source, QOverload<int>::of(&QComboBox::currentIndexChanged), this, connect(ui->bcat_source, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
&ConfigureService::OnBCATImplChanged); &ConfigureNetwork::OnBCATImplChanged);
this->SetConfiguration(); this->SetConfiguration();
} }
ConfigureService::~ConfigureService() = default; ConfigureNetwork::~ConfigureNetwork() = default;
void ConfigureService::ApplyConfiguration() { void ConfigureNetwork::ApplyConfiguration() {
Settings::values.bcat_backend = ui->bcat_source->currentText().toLower().toStdString(); Settings::values.bcat_backend = ui->bcat_source->currentText().toLower().toStdString();
Settings::values.network_interface = ui->network_interface->currentText().toStdString();
} }
void ConfigureService::RetranslateUi() { void ConfigureNetwork::RetranslateUi() {
ui->retranslateUi(this); ui->retranslateUi(this);
} }
void ConfigureService::SetConfiguration() { void ConfigureNetwork::SetConfiguration() {
const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn();
const int index = const int index =
ui->bcat_source->findData(QString::fromStdString(Settings::values.bcat_backend.GetValue())); ui->bcat_source->findData(QString::fromStdString(Settings::values.bcat_backend.GetValue()));
ui->bcat_source->setCurrentIndex(index == -1 ? 0 : index); ui->bcat_source->setCurrentIndex(index == -1 ? 0 : index);
const std::string& network_interface = Settings::values.network_interface.GetValue();
ui->network_interface->setCurrentText(QString::fromStdString(network_interface));
ui->network_interface->setEnabled(runtime_lock);
} }
std::pair<QString, QString> ConfigureService::BCATDownloadEvents() { std::pair<QString, QString> ConfigureNetwork::BCATDownloadEvents() {
#ifdef YUZU_ENABLE_BOXCAT #ifdef YUZU_ENABLE_BOXCAT
std::optional<std::string> global; std::optional<std::string> global;
std::map<std::string, Service::BCAT::EventStatus> map; std::map<std::string, Service::BCAT::EventStatus> map;
@ -114,7 +128,7 @@ std::pair<QString, QString> ConfigureService::BCATDownloadEvents() {
#endif #endif
} }
void ConfigureService::OnBCATImplChanged() { void ConfigureNetwork::OnBCATImplChanged() {
#ifdef YUZU_ENABLE_BOXCAT #ifdef YUZU_ENABLE_BOXCAT
const auto boxcat = ui->bcat_source->currentText() == QStringLiteral("Boxcat"); const auto boxcat = ui->bcat_source->currentText() == QStringLiteral("Boxcat");
ui->bcat_empty_header->setHidden(!boxcat); ui->bcat_empty_header->setHidden(!boxcat);
@ -133,7 +147,7 @@ void ConfigureService::OnBCATImplChanged() {
#endif #endif
} }
void ConfigureService::OnUpdateBCATEmptyLabel(std::pair<QString, QString> string) { void ConfigureNetwork::OnUpdateBCATEmptyLabel(std::pair<QString, QString> string) {
#ifdef YUZU_ENABLE_BOXCAT #ifdef YUZU_ENABLE_BOXCAT
const auto boxcat = ui->bcat_source->currentText() == QStringLiteral("Boxcat"); const auto boxcat = ui->bcat_source->currentText() == QStringLiteral("Boxcat");
if (boxcat) { if (boxcat) {

View file

@ -8,16 +8,18 @@
#include <QFutureWatcher> #include <QFutureWatcher>
#include <QWidget> #include <QWidget>
#include "core/network/network_interface.h"
namespace Ui { namespace Ui {
class ConfigureService; class ConfigureNetwork;
} }
class ConfigureService : public QWidget { class ConfigureNetwork : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit ConfigureService(QWidget* parent = nullptr); explicit ConfigureNetwork(QWidget* parent = nullptr);
~ConfigureService() override; ~ConfigureNetwork() override;
void ApplyConfiguration(); void ApplyConfiguration();
void RetranslateUi(); void RetranslateUi();
@ -29,6 +31,6 @@ private:
void OnBCATImplChanged(); void OnBCATImplChanged();
void OnUpdateBCATEmptyLabel(std::pair<QString, QString> string); void OnUpdateBCATEmptyLabel(std::pair<QString, QString> string);
std::unique_ptr<Ui::ConfigureService> ui; std::unique_ptr<Ui::ConfigureNetwork> ui;
QFutureWatcher<std::pair<QString, QString>> watcher{this}; QFutureWatcher<std::pair<QString, QString>> watcher{this};
}; };

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0"> <ui version="4.0">
<class>ConfigureService</class> <class>ConfigureNetwork</class>
<widget class="QWidget" name="ConfigureService"> <widget class="QWidget" name="ConfigureNetwork">
<property name="geometry"> <property name="geometry">
<rect> <rect>
<x>0</x> <x>0</x>
@ -16,22 +16,38 @@
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
<item> <item>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>General</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="1" column="1">
<widget class="QComboBox" name="network_interface"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Network Interface</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item> <item>
<widget class="QGroupBox" name="groupBox"> <widget class="QGroupBox" name="groupBox">
<property name="title"> <property name="title">
<string>BCAT</string> <string>BCAT</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="1" column="1" colspan="2"> <item row="3" column="0">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="bcat_empty_header">
<property name="maximumSize">
<size>
<width>260</width>
<height>16777215</height>
</size>
</property>
<property name="text"> <property name="text">
<string>BCAT is Nintendo's way of sending data to games to engage its community and unlock additional content.</string> <string/>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
@ -51,11 +67,8 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1" colspan="2"> <item row="1" column="1" colspan="2">
<widget class="QLabel" name="bcat_empty_label"> <widget class="QLabel" name="label_2">
<property name="enabled">
<bool>true</bool>
</property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>260</width> <width>260</width>
@ -63,10 +76,7 @@
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string/> <string>BCAT is Nintendo's way of sending data to games to engage its community and unlock additional content.</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property> </property>
<property name="wordWrap"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
@ -86,8 +96,17 @@
<item row="0" column="1" colspan="2"> <item row="0" column="1" colspan="2">
<widget class="QComboBox" name="bcat_source"/> <widget class="QComboBox" name="bcat_source"/>
</item> </item>
<item row="3" column="0"> <item row="3" column="1" colspan="2">
<widget class="QLabel" name="bcat_empty_header"> <widget class="QLabel" name="bcat_empty_label">
<property name="enabled">
<bool>true</bool>
</property>
<property name="maximumSize">
<size>
<width>260</width>
<height>16777215</height>
</size>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>