Skip to content

Commit

Permalink
RMG: improve UI behavior of NetplaySessionBrowserDialog
Browse files Browse the repository at this point in the history
  • Loading branch information
Rosalie241 committed Dec 27, 2024
1 parent d3d1fac commit 157dd07
Show file tree
Hide file tree
Showing 11 changed files with 602 additions and 125 deletions.
4 changes: 4 additions & 0 deletions Source/RMG/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@ if (NETPLAY)
UserInterface/Dialog/Netplay/NetplaySessionDialog.ui
UserInterface/Dialog/Netplay/NetplaySessionPasswordDialog.cpp
UserInterface/Dialog/Netplay/NetplaySessionPasswordDialog.ui
UserInterface/Widget/Netplay/NetplaySessionBrowserWidget.cpp
UserInterface/Widget/Netplay/NetplaySessionBrowserLoadingWidget.cpp
UserInterface/Widget/Netplay/NetplaySessionBrowserEmptyWidget.cpp
UserInterface/Widget/Netplay/NetplaySessionBrowserEmptyWidget.ui
)
endif(NETPLAY)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "NetplaySessionBrowserDialog.hpp"
#include "UserInterface/NoFocusDelegate.hpp"
#include "NetplaySessionPasswordDialog.hpp"
#include "NetplayCommon.hpp"
#include "Utilities/QtMessageBox.hpp"
Expand All @@ -27,37 +26,18 @@
using namespace UserInterface::Dialog;
using namespace Utilities;

//
// Local Structs
//

struct NetplaySessionData_t
{
QString SessionName;
QString GameName;
QString MD5;
bool PasswordProtected = false;
int Port = 0;
QString CpuEmulator;
QString RspPlugin;
QString GfxPlugin;
};

Q_DECLARE_METATYPE(NetplaySessionData_t);

//
// Exported Functions
//

NetplaySessionBrowserDialog::NetplaySessionBrowserDialog(QWidget *parent, QWebSocket* webSocket, QMap<QString, CoreRomSettings> modelData) : QDialog(parent)
{
qRegisterMetaType<NetplaySessionData_t>();

this->setupUi(this);

// prepare web socket
this->webSocket = webSocket;
connect(this->webSocket, &QWebSocket::connected, this, &NetplaySessionBrowserDialog::on_webSocket_connected);
connect(this->webSocket, &QWebSocket::disconnected, this, &NetplaySessionBrowserDialog::on_webSocket_disconnected);
connect(this->webSocket, &QWebSocket::textMessageReceived, this, &NetplaySessionBrowserDialog::on_webSocket_textMessageReceived);

// copy rom data for later
Expand Down Expand Up @@ -86,25 +66,6 @@ NetplaySessionBrowserDialog::NetplaySessionBrowserDialog(QWidget *parent, QWebSo
this->nickNameLineEdit->setValidator(new QRegularExpressionValidator(re, this));
this->nickNameLineEdit->setText(QString::fromStdString(CoreSettingsGetStringValue(SettingsID::Netplay_Nickname)));

// prepare session browser
this->tableWidget->setFrameStyle(QFrame::NoFrame);
this->tableWidget->setItemDelegate(new NoFocusDelegate(this));
this->tableWidget->setWordWrap(false);
this->tableWidget->setShowGrid(false);
this->tableWidget->setSortingEnabled(true);
this->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
this->tableWidget->setSelectionBehavior(QTableView::SelectRows);
this->tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
this->tableWidget->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel);
this->tableWidget->verticalHeader()->hide();
this->tableWidget->verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
this->tableWidget->horizontalHeader()->setSectionsMovable(true);
this->tableWidget->horizontalHeader()->setFirstSectionMovable(true);
this->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
this->tableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
this->tableWidget->horizontalHeader()->setSortIndicatorShown(false);
this->tableWidget->horizontalHeader()->setHighlightSections(false);

// request server list
QString serverUrl = QString::fromStdString(CoreSettingsGetStringValue(SettingsID::Netplay_ServerJsonUrl));
if (!serverUrl.isEmpty() && QUrl(serverUrl).isValid())
Expand Down Expand Up @@ -174,7 +135,7 @@ bool NetplaySessionBrowserDialog::validate(void)
return false;
}

if (this->tableWidget->currentItem() == nullptr ||
if (!this->sessionBrowserWidget->IsCurrentSessionValid() ||
this->serverComboBox->count() == 0)
{
return false;
Expand All @@ -189,51 +150,24 @@ void NetplaySessionBrowserDialog::validateJoinButton(void)
joinButton->setEnabled(this->validate());
}

void NetplaySessionBrowserDialog::addSessionData(QString name, QString game, QString md5, bool password, int port,
QString cpuEmulator, QString rspPlugin, QString gfxPlugin)
{
const NetplaySessionData_t sessionData =
{
name,
game,
md5,
password,
port,
cpuEmulator,
rspPlugin,
gfxPlugin
};

int row = this->tableWidget->rowCount();
this->tableWidget->insertRow(row);

// Session name
QTableWidgetItem* tableWidgetItem1 = new QTableWidgetItem(name);
tableWidgetItem1->setData(Qt::UserRole, QVariant::fromValue<NetplaySessionData_t>(sessionData));
this->tableWidget->setItem(row, 0, tableWidgetItem1);

// Game
QTableWidgetItem* tableWidgetItem2 = new QTableWidgetItem(game);
this->tableWidget->setItem(row, 1, tableWidgetItem2);

// MD5
QTableWidgetItem* tableWidgetItem3 = new QTableWidgetItem(md5);
this->tableWidget->setItem(row, 2, tableWidgetItem3);

// Password
QTableWidgetItem* tableWidgetItem4 = new QTableWidgetItem(password ? "Yes" : "No");
this->tableWidget->setItem(row, 3, tableWidgetItem4);
}

void NetplaySessionBrowserDialog::on_webSocket_connected(void)
{
if (!this->webSocket->isValid())
{
QtMessageBox::Error(this, "Server Error", "Connection Failed");
return;
}

// clear sessions from the table
this->tableWidget->model()->removeRows(0, this->tableWidget->rowCount());
// disable refresh button while refreshing
QPushButton* refreshButton = this->buttonBox->button(QDialogButtonBox::RestoreDefaults);
refreshButton->setEnabled(false);

// disable join button while refreshing
QPushButton* joinButton = this->buttonBox->button(QDialogButtonBox::Ok);
joinButton->setEnabled(false);

// clear sessions
this->sessionBrowserWidget->StartRefresh();

// request session list from server
QJsonObject json;
Expand All @@ -254,14 +188,30 @@ void NetplaySessionBrowserDialog::on_webSocket_textMessageReceived(QString messa
{
if (json.value("accept").toInt() == 0)
{
this->addSessionData(json.value("room_name").toString(),
json.value("game_name").toString(),
json.value("MD5").toString(),
json.value("protected").toBool(),
json.value("port").toInt(),
json.value("features").toObject().value("cpu_emulator").toString(),
json.value("features").toObject().value("rsp_plugin").toString(),
json.value("features").toObject().value("gfx_plugin").toString());
this->sessionBrowserWidget->AddSessionData(json.value("room_name").toString(),
json.value("game_name").toString(),
json.value("MD5").toString(),
json.value("protected").toBool(),
json.value("port").toInt(),
json.value("features").toObject().value("cpu_emulator").toString(),
json.value("features").toObject().value("rsp_plugin").toString(),
json.value("features").toObject().value("gfx_plugin").toString());
}
else
{
QtMessageBox::Error(this, "Server Error", json.value("message").toString());
}
}
else if (type == "reply_get_rooms_done")
{
if (json.value("accept").toInt() == 0)
{
this->sessionBrowserWidget->RefreshDone();
// enable refresh button when refreshing is done
QPushButton* refreshButton = this->buttonBox->button(QDialogButtonBox::RestoreDefaults);
refreshButton->setEnabled(true);
// re-validate join button after refresh
this->validateJoinButton();
}
else
{
Expand All @@ -283,6 +233,11 @@ void NetplaySessionBrowserDialog::on_webSocket_textMessageReceived(QString messa
}
}

void NetplaySessionBrowserDialog::on_webSocket_disconnected()
{
this->sessionBrowserWidget->Reset();
}

void NetplaySessionBrowserDialog::on_broadcastSocket_readyRead(void)
{
while (this->broadcastSocket.hasPendingDatagrams())
Expand All @@ -304,6 +259,8 @@ void NetplaySessionBrowserDialog::on_networkAccessManager_Finished(QNetworkReply
{
if (reply->error())
{
this->sessionBrowserWidget->Reset();
QtMessageBox::Error(this, "Server Error", "Failed to retrieve json server list: " + reply->errorString());
reply->deleteLater();
return;
}
Expand All @@ -330,14 +287,13 @@ void NetplaySessionBrowserDialog::on_serverComboBox_currentIndexChanged(int inde
return;
}

// clear sessions from the table
this->tableWidget->model()->removeRows(0, this->tableWidget->rowCount());
this->sessionBrowserWidget->StartRefresh();

QString address = this->serverComboBox->itemData(index).toString();
this->webSocket->open(QUrl(address));
}

void NetplaySessionBrowserDialog::on_tableWidget_currentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous)
void NetplaySessionBrowserDialog::on_sessionBrowserWidget_OnSessionChanged(bool valid)
{
this->validateJoinButton();
}
Expand All @@ -364,14 +320,17 @@ void NetplaySessionBrowserDialog::accept()
return;
}

// retrieve session data
NetplaySessionData sessionData;
if (!this->sessionBrowserWidget->GetCurrentSession(sessionData))
{
return;
}

// disable join button while we're processing the request
QPushButton* joinButton = this->buttonBox->button(QDialogButtonBox::Ok);
joinButton->setEnabled(false);

// retrieve information from row
QTableWidgetItem* item = this->tableWidget->item(this->tableWidget->currentRow(), 0);
NetplaySessionData_t sessionData = item->data(Qt::UserRole).value<NetplaySessionData_t>();

// request password when needed
QString password;
if (sessionData.PasswordProtected)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,16 @@ class NetplaySessionBrowserDialog : public QDialog, private Ui::NetplaySessionBr
bool validate(void);
void validateJoinButton(void);

void addSessionData(QString name, QString game, QString md5, bool password, int port,
QString cpuEmulator, QString rspPlugin, QString gfxPlugin);

private slots:
void on_webSocket_connected(void);
void on_webSocket_textMessageReceived(QString message);
void on_webSocket_disconnected(void);

void on_broadcastSocket_readyRead(void);
void on_networkAccessManager_Finished(QNetworkReply* reply);

void on_serverComboBox_currentIndexChanged(int index);
void on_tableWidget_currentItemChanged(QTableWidgetItem* current, QTableWidgetItem* previous);
void on_sessionBrowserWidget_OnSessionChanged(bool valid);

void on_nickNameLineEdit_textChanged(void);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,33 +50,15 @@
</layout>
</item>
<item>
<widget class="QTableWidget" name="tableWidget">
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Game</string>
</property>
</column>
<column>
<property name="text">
<string>Game MD5</string>
</property>
</column>
<column>
<property name="text">
<string>Password?</string>
</property>
</column>
<widget class="UserInterface::Widget::NetplaySessionBrowserWidget" name="sessionBrowserWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QWidget" name="page"/>
<widget class="QWidget" name="page_2"/>
</widget>
</item>
<item>
Expand All @@ -91,6 +73,14 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>UserInterface::Widget::NetplaySessionBrowserWidget</class>
<extends>QStackedWidget</extends>
<header>UserInterface/Widget/Netplay/NetplaySessionBrowserWidget.hpp</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections>
<connection>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
* Copyright (C) 2020 Rosalie Wanders <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "NetplaySessionBrowserEmptyWidget.hpp"

#include <QLabel>
#include <QHBoxLayout>
#include <QDragMoveEvent>
#include <QDragEnterEvent>
#include <QMimeData>

using namespace UserInterface::Widget;

NetplaySessionBrowserEmptyWidget::NetplaySessionBrowserEmptyWidget(QWidget* parent) : QWidget(parent)
{
this->setupUi(this);
}

NetplaySessionBrowserEmptyWidget::~NetplaySessionBrowserEmptyWidget()
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Rosalie's Mupen GUI - https://github.com/Rosalie241/RMG
* Copyright (C) 2020 Rosalie Wanders <[email protected]>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef NETPLAYSESSIONBROWSEREMPTYWIDGET_HPP
#define NETPLAYSESSIONBROWSEREMPTYWIDGET_HPP

#include <QWidget>

#include "ui_NetplaySessionBrowserEmptyWidget.h"

namespace UserInterface
{
namespace Widget
{
class NetplaySessionBrowserEmptyWidget : public QWidget, private Ui::NetplaySessionBrowserEmptyWidget
{
Q_OBJECT
public:
NetplaySessionBrowserEmptyWidget(QWidget* parent);
~NetplaySessionBrowserEmptyWidget();
};
} // namespace Widget
} // namespace UserInterface

#endif // NETPLAYSESSIONBROWSEREMPTYWIDGET_HPP
Loading

0 comments on commit 157dd07

Please sign in to comment.