Clans: Qt GUI configuration impl

Signed-off-by: zeph <35661622+ZephyrCodesStuff@users.noreply.github.com>
This commit is contained in:
zeph 2025-12-07 18:11:22 +01:00
parent e47f224bc2
commit d618ec9135
No known key found for this signature in database
11 changed files with 423 additions and 38 deletions

View File

@ -441,7 +441,8 @@ target_sources(rpcs3_emu PRIVATE
NP/np_requests.cpp
NP/signaling_handler.cpp
NP/np_structs_extra.cpp
NP/clan_client.cpp
NP/clans_client.cpp
NP/clans_config.cpp
NP/rpcn_client.cpp
NP/rpcn_config.cpp
NP/rpcn_countries.cpp

View File

@ -2,7 +2,7 @@
#include "Emu/Cell/PPUModule.h"
#include "Emu/IdManager.h"
#include "Emu/NP/np_handler.h"
#include "Emu/NP/clan_client.h"
#include "Emu/NP/clans_client.h"
#include "sceNp.h"
#include "sceNpClans.h"
@ -97,7 +97,7 @@ error_code sceNpClansInit(vm::cptr<SceNpCommunicationId> commId, vm::cptr<SceNpC
}
// Allocate space for a client somewhere
clan::clan_client* client = new clan::clan_client();
clan::clans_client* client = new clan::clans_client();
clans_manager.client = client;
clans_manager.is_initialized = true;

View File

@ -2,7 +2,7 @@
#include "util/types.hpp"
#include <Crypto/utils.h>
#include <Emu/NP/clan_client.h>
#include <Emu/NP/clans_client.h>
#include <format>
#include <wolfssl/wolfcrypt/coding.h>
@ -118,7 +118,7 @@ namespace clan
size_t size;
};
size_t clan_client::curlWriteCallback(void* data, size_t size, size_t nmemb, void* clientp)
size_t clans_client::curlWriteCallback(void* data, size_t size, size_t nmemb, void* clientp)
{
size_t realsize = size * nmemb;
std::vector<char>* mem = static_cast<std::vector<char>*>(clientp);
@ -130,17 +130,17 @@ namespace clan
return realsize;
}
clan_client::clan_client()
clans_client::clans_client()
{
createRequest();
}
clan_client::~clan_client()
clans_client::~clans_client()
{
destroyRequest();
}
SceNpClansError clan_client::createRequest()
SceNpClansError clans_client::createRequest()
{
if (curl)
return SceNpClansError::SCE_NP_CLANS_ERROR_ALREADY_INITIALIZED;
@ -156,7 +156,7 @@ namespace clan
return SceNpClansError::SCE_NP_CLANS_SUCCESS;
}
SceNpClansError clan_client::destroyRequest()
SceNpClansError clans_client::destroyRequest()
{
if (curl)
{
@ -167,7 +167,7 @@ namespace clan
return SceNpClansError::SCE_NP_CLANS_SUCCESS;
}
SceNpClansError clan_client::sendRequest(ClanRequestAction action, ClanManagerOperationType opType, pugi::xml_document* xmlBody, pugi::xml_document* outResponse)
SceNpClansError clans_client::sendRequest(ClanRequestAction action, ClanManagerOperationType opType, pugi::xml_document* xmlBody, pugi::xml_document* outResponse)
{
if (!curl)
return SCE_NP_CLANS_ERROR_NOT_INITIALIZED;
@ -237,7 +237,7 @@ namespace clan
return SCE_NP_CLANS_SUCCESS;
}
std::string clan_client::getClanTicket(np::np_handler& nph)
std::string clans_client::getClanTicket(np::np_handler& nph)
{
if (nph.get_ticket().size() > 0) {
std::vector<byte> ticket_bytes(1024);
@ -287,7 +287,7 @@ namespace clan
}
#pragma region Outgoing API Requests
SceNpClansError clan_client::getClanList(np::np_handler& nph, SceNpClansPagingRequest* paging, SceNpClansEntry* clanList, SceNpClansPagingResult* pageResult)
SceNpClansError clans_client::getClanList(np::np_handler& nph, SceNpClansPagingRequest* paging, SceNpClansEntry* clanList, SceNpClansPagingResult* pageResult)
{
pugi::xml_document doc = pugi::xml_document();
pugi::xml_node clan = doc.append_child("clan");
@ -361,7 +361,7 @@ namespace clan
return SCE_NP_CLANS_SUCCESS;
}
SceNpClansError clan_client::getClanInfo(SceNpClanId clanId, SceNpClansClanInfo* clanInfo)
SceNpClansError clans_client::getClanInfo(SceNpClanId clanId, SceNpClansClanInfo* clanInfo)
{
pugi::xml_document doc = pugi::xml_document();
pugi::xml_node clan = doc.append_child("clan");
@ -400,7 +400,7 @@ namespace clan
return SCE_NP_CLANS_SUCCESS;
}
SceNpClansError clan_client::getMemberInfo(np::np_handler& nph, SceNpClanId clanId, SceNpId npId, SceNpClansMemberEntry* memInfo)
SceNpClansError clans_client::getMemberInfo(np::np_handler& nph, SceNpClanId clanId, SceNpId npId, SceNpClansMemberEntry* memInfo)
{
std::string ticket = getClanTicket(nph);
@ -468,7 +468,7 @@ namespace clan
return SCE_NP_CLANS_SUCCESS;
}
SceNpClansError clan_client::getMemberList(np::np_handler& nph, SceNpClanId clanId, SceNpClansPagingRequest* paging, SceNpClansMemberStatus /*status*/, SceNpClansMemberEntry* memList, SceNpClansPagingResult* pageResult)
SceNpClansError clans_client::getMemberList(np::np_handler& nph, SceNpClanId clanId, SceNpClansPagingRequest* paging, SceNpClansMemberStatus /*status*/, SceNpClansMemberEntry* memList, SceNpClansPagingResult* pageResult)
{
std::string ticket = getClanTicket(nph);
@ -544,7 +544,7 @@ namespace clan
return SCE_NP_CLANS_SUCCESS;
}
SceNpClansError clan_client::getBlacklist(np::np_handler& nph, SceNpClanId clanId, SceNpClansPagingRequest* paging, SceNpClansBlacklistEntry* bl, SceNpClansPagingResult* pageResult)
SceNpClansError clans_client::getBlacklist(np::np_handler& nph, SceNpClanId clanId, SceNpClansPagingRequest* paging, SceNpClansBlacklistEntry* bl, SceNpClansPagingResult* pageResult)
{
std::string ticket = getClanTicket(nph);
@ -608,7 +608,7 @@ namespace clan
return SCE_NP_CLANS_SUCCESS;
}
SceNpClansError clan_client::addBlacklistEntry(np::np_handler& nph, SceNpClanId clanId, SceNpId npId)
SceNpClansError clans_client::addBlacklistEntry(np::np_handler& nph, SceNpClanId clanId, SceNpId npId)
{
std::string ticket = getClanTicket(nph);
@ -624,7 +624,7 @@ namespace clan
return sendRequest(ClanRequestAction::RecordBlacklistEntry, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::removeBlacklistEntry(np::np_handler& nph, SceNpClanId clanId, SceNpId npId)
SceNpClansError clans_client::removeBlacklistEntry(np::np_handler& nph, SceNpClanId clanId, SceNpId npId)
{
std::string ticket = getClanTicket(nph);
@ -640,7 +640,7 @@ namespace clan
return sendRequest(ClanRequestAction::DeleteBlacklistEntry, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::clanSearch(SceNpClansPagingRequest* paging, SceNpClansSearchableName* search, SceNpClansClanBasicInfo* clanList, SceNpClansPagingResult* pageResult)
SceNpClansError clans_client::clanSearch(SceNpClansPagingRequest* paging, SceNpClansSearchableName* search, SceNpClansClanBasicInfo* clanList, SceNpClansPagingResult* pageResult)
{
pugi::xml_document doc = pugi::xml_document();
pugi::xml_node clan = doc.append_child("clan");
@ -702,7 +702,7 @@ namespace clan
return SCE_NP_CLANS_SUCCESS;
}
SceNpClansError clan_client::requestMembership(np::np_handler& nph, SceNpClanId clanId, SceNpClansMessage* /*message*/)
SceNpClansError clans_client::requestMembership(np::np_handler& nph, SceNpClanId clanId, SceNpClansMessage* /*message*/)
{
std::string ticket = getClanTicket(nph);
@ -715,7 +715,7 @@ namespace clan
return sendRequest(ClanRequestAction::RequestMembership, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::cancelRequestMembership(np::np_handler& nph, SceNpClanId clanId)
SceNpClansError clans_client::cancelRequestMembership(np::np_handler& nph, SceNpClanId clanId)
{
std::string ticket = getClanTicket(nph);
@ -728,7 +728,7 @@ namespace clan
return sendRequest(ClanRequestAction::CancelRequestMembership, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::sendMembershipResponse(np::np_handler& nph, SceNpClanId clanId, SceNpId npId, SceNpClansMessage* /*message*/, b8 allow)
SceNpClansError clans_client::sendMembershipResponse(np::np_handler& nph, SceNpClanId clanId, SceNpId npId, SceNpClansMessage* /*message*/, b8 allow)
{
std::string ticket = getClanTicket(nph);
@ -744,7 +744,7 @@ namespace clan
return sendRequest(allow ? ClanRequestAction::AcceptMembershipRequest : ClanRequestAction::DeclineMembershipRequest, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::sendInvitation(np::np_handler& nph, SceNpClanId clanId, SceNpId npId, SceNpClansMessage* /*message*/)
SceNpClansError clans_client::sendInvitation(np::np_handler& nph, SceNpClanId clanId, SceNpId npId, SceNpClansMessage* /*message*/)
{
std::string ticket = getClanTicket(nph);
@ -760,7 +760,7 @@ namespace clan
return sendRequest(ClanRequestAction::SendInvitation, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::cancelInvitation(np::np_handler& nph, SceNpClanId clanId, SceNpId npId)
SceNpClansError clans_client::cancelInvitation(np::np_handler& nph, SceNpClanId clanId, SceNpId npId)
{
std::string ticket = getClanTicket(nph);
@ -776,7 +776,7 @@ namespace clan
return sendRequest(ClanRequestAction::CancelInvitation, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::sendInvitationResponse(np::np_handler& nph, SceNpClanId clanId, SceNpClansMessage* /*message*/, b8 accept)
SceNpClansError clans_client::sendInvitationResponse(np::np_handler& nph, SceNpClanId clanId, SceNpClansMessage* /*message*/, b8 accept)
{
std::string ticket = getClanTicket(nph);
@ -789,7 +789,7 @@ namespace clan
return sendRequest(accept ? ClanRequestAction::AcceptInvitation : ClanRequestAction::DeclineInvitation, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::updateMemberInfo(np::np_handler& nph, SceNpClanId clanId, SceNpClansUpdatableMemberInfo* info)
SceNpClansError clans_client::updateMemberInfo(np::np_handler& nph, SceNpClanId clanId, SceNpClansUpdatableMemberInfo* info)
{
std::string ticket = getClanTicket(nph);
@ -826,7 +826,7 @@ namespace clan
return sendRequest(ClanRequestAction::UpdateMemberInfo, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::updateClanInfo(np::np_handler& nph, SceNpClanId clanId, SceNpClansUpdatableClanInfo* info)
SceNpClansError clans_client::updateClanInfo(np::np_handler& nph, SceNpClanId clanId, SceNpClansUpdatableClanInfo* info)
{
std::string ticket = getClanTicket(nph);
@ -844,7 +844,7 @@ namespace clan
return sendRequest(ClanRequestAction::UpdateClanInfo, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::joinClan(np::np_handler& nph, SceNpClanId clanId)
SceNpClansError clans_client::joinClan(np::np_handler& nph, SceNpClanId clanId)
{
std::string ticket = getClanTicket(nph);
@ -857,7 +857,7 @@ namespace clan
return sendRequest(ClanRequestAction::JoinClan, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::leaveClan(np::np_handler& nph, SceNpClanId clanId)
SceNpClansError clans_client::leaveClan(np::np_handler& nph, SceNpClanId clanId)
{
std::string ticket = getClanTicket(nph);
@ -870,7 +870,7 @@ namespace clan
return sendRequest(ClanRequestAction::LeaveClan, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::kickMember(np::np_handler& nph, SceNpClanId clanId, SceNpId npId, SceNpClansMessage* /*message*/)
SceNpClansError clans_client::kickMember(np::np_handler& nph, SceNpClanId clanId, SceNpId npId, SceNpClansMessage* /*message*/)
{
std::string ticket = getClanTicket(nph);
@ -886,7 +886,7 @@ namespace clan
return sendRequest(ClanRequestAction::KickMember, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::changeMemberRole(np::np_handler& nph, SceNpClanId clanId, SceNpId npId, SceNpClansMemberRole role)
SceNpClansError clans_client::changeMemberRole(np::np_handler& nph, SceNpClanId clanId, SceNpId npId, SceNpClansMemberRole role)
{
std::string ticket = getClanTicket(nph);
@ -905,7 +905,7 @@ namespace clan
return sendRequest(ClanRequestAction::ChangeMemberRole, ClanManagerOperationType::UPDATE, &doc, &response);
}
SceNpClansError clan_client::retrieveAnnouncements(np::np_handler& nph, SceNpClanId clanId, SceNpClansPagingRequest* paging, SceNpClansMessageEntry* announcements, SceNpClansPagingResult* pageResult)
SceNpClansError clans_client::retrieveAnnouncements(np::np_handler& nph, SceNpClanId clanId, SceNpClansPagingRequest* paging, SceNpClansMessageEntry* announcements, SceNpClansPagingResult* pageResult)
{
std::string ticket = getClanTicket(nph);
@ -987,7 +987,7 @@ namespace clan
return SCE_NP_CLANS_SUCCESS;
}
SceNpClansError clan_client::postAnnouncement(np::np_handler& nph, SceNpClanId clanId, SceNpClansMessage* announcement, SceNpClansMessageData* /*data*/, u32 duration, SceNpClansMessageId* msgId)
SceNpClansError clans_client::postAnnouncement(np::np_handler& nph, SceNpClanId clanId, SceNpClansMessage* announcement, SceNpClansMessageData* /*data*/, u32 duration, SceNpClansMessageId* msgId)
{
std::string ticket = getClanTicket(nph);
@ -1018,7 +1018,7 @@ namespace clan
return SCE_NP_CLANS_SUCCESS;
}
SceNpClansError clan_client::deleteAnnouncement(np::np_handler& nph, SceNpClanId clanId, SceNpClansMessageId announcementId)
SceNpClansError clans_client::deleteAnnouncement(np::np_handler& nph, SceNpClanId clanId, SceNpClansMessageId announcementId)
{
std::string ticket = getClanTicket(nph);

View File

@ -59,7 +59,7 @@ namespace clan
DeleteAnnouncement
};
class clan_client
class clans_client
{
private:
CURL* curl = nullptr;
@ -72,8 +72,8 @@ namespace clan
std::string getClanTicket(np::np_handler& nph);
public:
clan_client();
~clan_client();
clans_client();
~clans_client();
SceNpClansError createRequest();
SceNpClansError destroyRequest();
@ -116,5 +116,5 @@ namespace clan
struct sce_np_clans_manager
{
atomic_t<bool> is_initialized = false;
clan::clan_client* client;
clan::clans_client* client;
};

View File

@ -0,0 +1,140 @@
#include "stdafx.h"
#include "clans_config.h"
#include "Utilities/File.h"
cfg_clans g_cfg_clans;
LOG_CHANNEL(clans_config_log, "clans_config");
void cfg_clans::load()
{
const std::string path = cfg_clans::get_path();
fs::file cfg_file(path, fs::read);
if (cfg_file)
{
clans_config_log.notice("Loading Clans config. Path: %s", path);
from_string(cfg_file.to_string());
}
else
{
clans_config_log.notice("Clans config missing. Using default settings. Path: %s", path);
from_default();
}
}
void cfg_clans::save() const
{
#ifdef _WIN32
const std::string path_to_cfg = fs::get_config_dir(true);
if (!fs::create_path(path_to_cfg))
{
clans_config_log.error("Could not create path: %s", path_to_cfg);
}
#endif
const std::string path = cfg_clans::get_path();
if (!cfg::node::save(path))
{
clans_config_log.error("Could not save config: %s (error=%s)", path, fs::g_tls_error);
}
}
std::string cfg_clans::get_path()
{
return fs::get_config_dir(true) + "clans.yml";
}
std::string cfg_clans::get_host() const
{
return host.to_string();
}
std::vector<std::pair<std::string, std::string>> cfg_clans::get_hosts()
{
std::vector<std::pair<std::string, std::string>> vec_hosts;
auto hosts_list = fmt::split(hosts.to_string(), {"|||"});
for (const auto& cur_host : hosts_list)
{
auto desc_and_host = fmt::split(cur_host, {"|"});
if (desc_and_host.size() != 2)
{
clans_config_log.error("Invalid host in the list of hosts: %s", cur_host);
continue;
}
vec_hosts.push_back(std::make_pair(std::move(desc_and_host[0]), std::move(desc_and_host[1])));
}
if (vec_hosts.empty())
{
hosts.from_default();
save();
return get_hosts();
}
return vec_hosts;
}
void cfg_clans::set_host(std::string_view host)
{
this->host.from_string(host);
}
void cfg_clans::set_hosts(const std::vector<std::pair<std::string, std::string>>& vec_hosts)
{
std::string final_string;
for (const auto& [cur_desc, cur_host] : vec_hosts)
{
fmt::append(final_string, "%s|%s|||", cur_desc, cur_host);
}
if (final_string.empty())
{
hosts.from_default();
return;
}
final_string.resize(final_string.size() - 3);
hosts.from_string(final_string);
}
bool cfg_clans::add_host(std::string_view new_description, std::string_view new_host)
{
auto cur_hosts = get_hosts();
for (const auto& [cur_desc, cur_host] : cur_hosts)
{
if (cur_desc == new_description && cur_host == new_host)
return false;
}
cur_hosts.push_back(std::make_pair(std::string(new_description), std::string(new_host)));
set_hosts(cur_hosts);
return true;
}
bool cfg_clans::del_host(std::string_view del_description, std::string_view del_host)
{
// Do not delete default servers
if (del_description == "Official Clans Server" && del_host == "clans.rpcs3.net")
{
return true;
}
auto cur_hosts = get_hosts();
for (auto it = cur_hosts.begin(); it != cur_hosts.end(); it++)
{
if (it->first == del_description && it->second == del_host)
{
cur_hosts.erase(it);
set_hosts(cur_hosts);
return true;
}
}
return false;
}

View File

@ -0,0 +1,26 @@
#pragma once
#include "Utilities/Config.h"
struct cfg_clans : cfg::node
{
cfg::uint32 version{this, "Version", 1};
cfg::string host{this, "Host", "clans.rpcs3.net"};
cfg::string hosts{this, "Hosts", "Official Clans Server|clans.rpcs3.net"};
void load();
void save() const;
std::string get_host() const;
std::vector<std::pair<std::string, std::string>> get_hosts();
void set_host(std::string_view host);
bool add_host(std::string_view description, std::string_view host);
bool del_host(std::string_view description, std::string_view host);
private:
static std::string get_path();
void set_hosts(const std::vector<std::pair<std::string, std::string>>& vec_hosts);
};
extern cfg_clans g_cfg_clans;

View File

@ -8,6 +8,7 @@ add_library(rpcs3_ui STATIC
camera_settings_dialog.cpp
cg_disasm_window.cpp
cheat_manager.cpp
clans_settings_dialog.cpp
config_adapter.cpp
config_checker.cpp
curl_handle.cpp

View File

@ -0,0 +1,172 @@
#include <QMessageBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QGroupBox>
#include <QDialogButtonBox>
#include <QLineEdit>
#include "clans_settings_dialog.h"
#include "Emu/NP/clans_config.h"
clans_settings_dialog::clans_settings_dialog(QWidget* parent)
: QDialog(parent)
{
g_cfg_clans.load();
setWindowTitle(tr("Clans Configuration"));
setObjectName("clans_settings_dialog");
QVBoxLayout* vbox_global = new QVBoxLayout();
QGroupBox* grp_server = new QGroupBox(tr("Server:"));
QVBoxLayout* vbox_server = new QVBoxLayout();
QHBoxLayout* hbox_lbl_combo = new QHBoxLayout();
QLabel* lbl_server = new QLabel(tr("Server:"));
cbx_servers = new QComboBox();
refresh_combobox();
hbox_lbl_combo->addWidget(lbl_server);
hbox_lbl_combo->addWidget(cbx_servers);
QHBoxLayout* hbox_buttons = new QHBoxLayout();
QPushButton* btn_add_server = new QPushButton(tr("Add"));
QPushButton* btn_del_server = new QPushButton(tr("Del"));
hbox_buttons->addStretch();
hbox_buttons->addWidget(btn_add_server);
hbox_buttons->addWidget(btn_del_server);
vbox_server->addLayout(hbox_lbl_combo);
vbox_server->addLayout(hbox_buttons);
grp_server->setLayout(vbox_server);
vbox_global->addWidget(grp_server);
setLayout(vbox_global);
connect(cbx_servers, &QComboBox::currentIndexChanged, this, [this](int index)
{
if (index < 0)
return;
QVariant host = cbx_servers->itemData(index);
if (!host.isValid() || !host.canConvert<QString>())
return;
g_cfg_clans.set_host(host.toString().toStdString());
g_cfg_clans.save();
});
connect(btn_add_server, &QAbstractButton::clicked, this, [this]()
{
clans_add_server_dialog dlg(this);
dlg.exec();
const auto& new_server = dlg.get_new_server();
if (new_server)
{
if (!g_cfg_clans.add_host(new_server->first, new_server->second))
{
QMessageBox::critical(this, tr("Existing Server"), tr("You already have a server with this description & hostname in the list."), QMessageBox::Ok);
return;
}
g_cfg_clans.save();
refresh_combobox();
}
});
connect(btn_del_server, &QAbstractButton::clicked, this, [this]()
{
const int index = cbx_servers->currentIndex();
if (index < 0)
return;
const std::string desc = cbx_servers->itemText(index).toStdString();
const std::string host = cbx_servers->itemData(index).toString().toStdString();
if (g_cfg_clans.del_host(desc, host))
{
g_cfg_clans.save();
refresh_combobox();
}
else
{
QMessageBox::warning(this, tr("Cannot Delete"), tr("This server cannot be deleted."), QMessageBox::Ok);
}
});
}
void clans_settings_dialog::refresh_combobox()
{
g_cfg_clans.load();
const auto vec_hosts = g_cfg_clans.get_hosts();
const auto cur_host = g_cfg_clans.get_host();
int i = 0, index = 0;
cbx_servers->clear();
for (const auto& [desc, host] : vec_hosts)
{
cbx_servers->addItem(QString::fromStdString(desc), QString::fromStdString(host));
if (cur_host == host)
index = i;
i++;
}
cbx_servers->setCurrentIndex(index);
}
clans_add_server_dialog::clans_add_server_dialog(QWidget* parent)
: QDialog(parent)
{
setWindowTitle(tr("Clans: Add Server"));
setObjectName("clans_add_server_dialog");
setMinimumSize(QSize(400, 200));
QVBoxLayout* vbox_global = new QVBoxLayout();
QLabel* lbl_description = new QLabel(tr("Description:"));
QLineEdit* edt_description = new QLineEdit();
QLabel* lbl_host = new QLabel(tr("Host:"));
QLineEdit* edt_host = new QLineEdit();
QDialogButtonBox* btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
vbox_global->addWidget(lbl_description);
vbox_global->addWidget(edt_description);
vbox_global->addWidget(lbl_host);
vbox_global->addWidget(edt_host);
vbox_global->addWidget(btn_box);
setLayout(vbox_global);
connect(btn_box, &QDialogButtonBox::accepted, this, [this, edt_description, edt_host]()
{
const QString description = edt_description->text();
const QString host = edt_host->text();
if (description.isEmpty())
{
QMessageBox::critical(this, tr("Missing Description!"), tr("You must enter a description!"), QMessageBox::Ok);
return;
}
if (host.isEmpty())
{
QMessageBox::critical(this, tr("Missing Hostname!"), tr("You must enter a hostname for the server!"), QMessageBox::Ok);
return;
}
m_new_server = std::make_pair(description.toStdString(), host.toStdString());
QDialog::accept();
});
connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
}
const std::optional<std::pair<std::string, std::string>>& clans_add_server_dialog::get_new_server() const
{
return m_new_server;
}

View File

@ -0,0 +1,29 @@
#pragma once
#include <optional>
#include <QDialog>
#include <QComboBox>
class clans_settings_dialog : public QDialog
{
Q_OBJECT
public:
clans_settings_dialog(QWidget* parent = nullptr);
private:
void refresh_combobox();
private:
QComboBox* cbx_servers = nullptr;
};
class clans_add_server_dialog : public QDialog
{
Q_OBJECT
public:
clans_add_server_dialog(QWidget* parent = nullptr);
const std::optional<std::pair<std::string, std::string>>& get_new_server() const;
private:
std::optional<std::pair<std::string, std::string>> m_new_server;
};

View File

@ -12,6 +12,7 @@
#include "log_frame.h"
#include "settings_dialog.h"
#include "rpcn_settings_dialog.h"
#include "clans_settings_dialog.h"
#include "auto_pause_settings_dialog.h"
#include "cg_disasm_window.h"
#include "log_viewer.h"
@ -2991,6 +2992,12 @@ void main_window::CreateConnects()
dlg.exec();
});
connect(ui->confClansAct, &QAction::triggered, this, [this]()
{
clans_settings_dialog dlg(this);
dlg.exec();
});
connect(ui->confIPCAct, &QAction::triggered, this, [this]()
{
ipc_settings_dialog dlg(this);

View File

@ -282,6 +282,7 @@
<addaction name="confGuiAct"/>
<addaction name="separator"/>
<addaction name="confRPCNAct"/>
<addaction name="confClansAct"/>
<addaction name="confIPCAct"/>
<addaction name="separator"/>
<addaction name="confShortcutsAct"/>
@ -1252,6 +1253,14 @@
<string>Configure RPCN</string>
</property>
</action>
<action name="confClansAct">
<property name="text">
<string>Clans</string>
</property>
<property name="toolTip">
<string>Configure Clans</string>
</property>
</action>
<action name="confIPCAct">
<property name="text">
<string>IPC</string>