2018-01-19 13:42:21 +00:00
|
|
|
// Copyright 2017 Citra Emulator Project
|
|
|
|
// Licensed under GPLv2 or any later version
|
|
|
|
// Refer to the license.txt file included.
|
|
|
|
|
|
|
|
#include <QComboBox>
|
|
|
|
#include <QFuture>
|
|
|
|
#include <QIntValidator>
|
|
|
|
#include <QRegExpValidator>
|
|
|
|
#include <QString>
|
|
|
|
#include <QtConcurrent/QtConcurrentRun>
|
|
|
|
#include "citra_qt/main.h"
|
|
|
|
#include "citra_qt/multiplayer/client_room.h"
|
|
|
|
#include "citra_qt/multiplayer/direct_connect.h"
|
|
|
|
#include "citra_qt/multiplayer/message.h"
|
2018-04-01 07:06:48 +01:00
|
|
|
#include "citra_qt/multiplayer/state.h"
|
2018-01-19 13:42:21 +00:00
|
|
|
#include "citra_qt/multiplayer/validation.h"
|
|
|
|
#include "citra_qt/ui_settings.h"
|
|
|
|
#include "core/settings.h"
|
|
|
|
#include "network/network.h"
|
2018-04-18 17:29:03 +01:00
|
|
|
#include "ui_direct_connect.h"
|
2018-01-19 13:42:21 +00:00
|
|
|
|
2018-04-09 18:00:56 +01:00
|
|
|
enum class ConnectionType : u8 { TraversalServer, IP };
|
2018-01-19 13:42:21 +00:00
|
|
|
|
|
|
|
DirectConnectWindow::DirectConnectWindow(QWidget* parent)
|
|
|
|
: QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
|
2018-04-18 06:06:02 +01:00
|
|
|
ui(std::make_unique<Ui::DirectConnect>()) {
|
2018-01-19 13:42:21 +00:00
|
|
|
|
|
|
|
ui->setupUi(this);
|
|
|
|
|
|
|
|
// setup the watcher for background connections
|
|
|
|
watcher = new QFutureWatcher<void>;
|
|
|
|
connect(watcher, &QFutureWatcher<void>::finished, this, &DirectConnectWindow::OnConnection);
|
|
|
|
|
2018-04-18 17:29:03 +01:00
|
|
|
ui->nickname->setValidator(validation.GetNickname());
|
2018-01-19 13:42:21 +00:00
|
|
|
ui->nickname->setText(UISettings::values.nickname);
|
2018-07-17 08:25:00 +01:00
|
|
|
if (ui->nickname->text().isEmpty() && !Settings::values.citra_username.empty()) {
|
|
|
|
// Use Citra Web Service user name as nickname by default
|
|
|
|
ui->nickname->setText(QString::fromStdString(Settings::values.citra_username));
|
|
|
|
}
|
2018-04-18 17:29:03 +01:00
|
|
|
ui->ip->setValidator(validation.GetIP());
|
2018-01-19 13:42:21 +00:00
|
|
|
ui->ip->setText(UISettings::values.ip);
|
2018-04-18 17:29:03 +01:00
|
|
|
ui->port->setValidator(validation.GetPort());
|
2018-01-19 13:42:21 +00:00
|
|
|
ui->port->setText(UISettings::values.port);
|
|
|
|
|
|
|
|
// TODO(jroweboy): Show or hide the connection options based on the current value of the combo
|
|
|
|
// box. Add this back in when the traversal server support is added.
|
|
|
|
connect(ui->connect, &QPushButton::pressed, this, &DirectConnectWindow::Connect);
|
|
|
|
}
|
|
|
|
|
2018-04-18 17:29:03 +01:00
|
|
|
DirectConnectWindow::~DirectConnectWindow() = default;
|
|
|
|
|
2018-01-19 13:42:21 +00:00
|
|
|
void DirectConnectWindow::Connect() {
|
|
|
|
if (!ui->nickname->hasAcceptableInput()) {
|
2018-04-09 18:00:56 +01:00
|
|
|
NetworkMessage::ShowError(NetworkMessage::USERNAME_NOT_VALID);
|
|
|
|
return;
|
2018-01-19 13:42:21 +00:00
|
|
|
}
|
|
|
|
if (const auto member = Network::GetRoomMember().lock()) {
|
2018-04-20 07:14:44 +01:00
|
|
|
// Prevent the user from trying to join a room while they are already joining.
|
|
|
|
if (member->GetState() == Network::RoomMember::State::Joining) {
|
2018-04-09 18:00:56 +01:00
|
|
|
return;
|
2018-04-20 07:14:44 +01:00
|
|
|
} else if (member->GetState() == Network::RoomMember::State::Joined) {
|
|
|
|
// And ask if they want to leave the room if they are already in one.
|
|
|
|
if (!NetworkMessage::WarnDisconnect()) {
|
|
|
|
return;
|
|
|
|
}
|
2018-01-19 13:42:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (static_cast<ConnectionType>(ui->connection_type->currentIndex())) {
|
2018-04-09 18:00:56 +01:00
|
|
|
case ConnectionType::TraversalServer:
|
2018-01-19 13:42:21 +00:00
|
|
|
break;
|
|
|
|
case ConnectionType::IP:
|
|
|
|
if (!ui->ip->hasAcceptableInput()) {
|
|
|
|
NetworkMessage::ShowError(NetworkMessage::IP_ADDRESS_NOT_VALID);
|
2018-04-09 18:00:56 +01:00
|
|
|
return;
|
2018-01-19 13:42:21 +00:00
|
|
|
}
|
|
|
|
if (!ui->port->hasAcceptableInput()) {
|
|
|
|
NetworkMessage::ShowError(NetworkMessage::PORT_NOT_VALID);
|
2018-04-09 18:00:56 +01:00
|
|
|
return;
|
2018-01-19 13:42:21 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Store settings
|
|
|
|
UISettings::values.nickname = ui->nickname->text();
|
|
|
|
UISettings::values.ip = ui->ip->text();
|
|
|
|
UISettings::values.port = (ui->port->isModified() && !ui->port->text().isEmpty())
|
|
|
|
? ui->port->text()
|
|
|
|
: UISettings::values.port;
|
|
|
|
Settings::Apply();
|
|
|
|
|
|
|
|
// attempt to connect in a different thread
|
|
|
|
QFuture<void> f = QtConcurrent::run([&] {
|
|
|
|
if (auto room_member = Network::GetRoomMember().lock()) {
|
|
|
|
auto port = UISettings::values.port.toUInt();
|
|
|
|
room_member->Join(ui->nickname->text().toStdString(),
|
|
|
|
ui->ip->text().toStdString().c_str(), port, 0,
|
|
|
|
Network::NoPreferredMac, ui->password->text().toStdString().c_str());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
watcher->setFuture(f);
|
|
|
|
// and disable widgets and display a connecting while we wait
|
|
|
|
BeginConnecting();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DirectConnectWindow::BeginConnecting() {
|
|
|
|
ui->connect->setEnabled(false);
|
|
|
|
ui->connect->setText(tr("Connecting"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void DirectConnectWindow::EndConnecting() {
|
|
|
|
ui->connect->setEnabled(true);
|
|
|
|
ui->connect->setText(tr("Connect"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void DirectConnectWindow::OnConnection() {
|
|
|
|
EndConnecting();
|
|
|
|
|
|
|
|
if (auto room_member = Network::GetRoomMember().lock()) {
|
2018-04-19 07:47:11 +01:00
|
|
|
if (room_member->GetState() == Network::RoomMember::State::Joined) {
|
2018-01-19 13:42:21 +00:00
|
|
|
close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|