From 2be02f221d58ca5ea31ac94b758289224e76a466 Mon Sep 17 00:00:00 2001
From: James Rowe <jroweboy@gmail.com>
Date: Wed, 18 Apr 2018 10:29:03 -0600
Subject: [PATCH] Fix player list not showing in lobby. Fix host and direct
 connect crashing citra

---
 src/citra_qt/multiplayer/chat_room.cpp      |  3 ++
 src/citra_qt/multiplayer/chat_room.h        |  6 +++-
 src/citra_qt/multiplayer/client_room.cpp    |  3 ++
 src/citra_qt/multiplayer/client_room.h      |  6 +++-
 src/citra_qt/multiplayer/direct_connect.cpp |  9 +++--
 src/citra_qt/multiplayer/direct_connect.h   |  8 ++++-
 src/citra_qt/multiplayer/host_room.cpp      |  9 +++--
 src/citra_qt/multiplayer/host_room.h        |  8 ++++-
 src/citra_qt/multiplayer/lobby.cpp          |  7 ++--
 src/citra_qt/multiplayer/lobby.h            |  2 ++
 src/citra_qt/multiplayer/validation.h       | 38 ++++++++++++---------
 11 files changed, 68 insertions(+), 31 deletions(-)

diff --git a/src/citra_qt/multiplayer/chat_room.cpp b/src/citra_qt/multiplayer/chat_room.cpp
index 877c99af4..5bb20bc12 100644
--- a/src/citra_qt/multiplayer/chat_room.cpp
+++ b/src/citra_qt/multiplayer/chat_room.cpp
@@ -16,6 +16,7 @@
 #include "citra_qt/multiplayer/message.h"
 #include "common/logging/log.h"
 #include "core/announce_multiplayer_session.h"
+#include "ui_chat_room.h"
 
 class ChatMessage {
 public:
@@ -102,6 +103,8 @@ ChatRoom::ChatRoom(QWidget* parent) : QWidget(parent), ui(std::make_unique<Ui::C
     connect(ui->send_message, &QPushButton::pressed, this, &ChatRoom::OnSendChat);
 }
 
+ChatRoom::~ChatRoom() = default;
+
 void ChatRoom::Clear() {
     ui->chat_history->clear();
 }
diff --git a/src/citra_qt/multiplayer/chat_room.h b/src/citra_qt/multiplayer/chat_room.h
index 440860459..4604c3395 100644
--- a/src/citra_qt/multiplayer/chat_room.h
+++ b/src/citra_qt/multiplayer/chat_room.h
@@ -10,7 +10,10 @@
 #include <QStandardItemModel>
 #include <QVariant>
 #include "network/network.h"
-#include "ui_chat_room.h"
+
+namespace Ui {
+class ChatRoom;
+}
 
 namespace Core {
 class AnnounceMultiplayerSession;
@@ -29,6 +32,7 @@ public:
     void SetPlayerList(const Network::RoomMember::MemberList& member_list);
     void Clear();
     void AppendStatusMessage(const QString& msg);
+    ~ChatRoom();
 
 public slots:
     void OnRoomUpdate(const Network::RoomInformation& info);
diff --git a/src/citra_qt/multiplayer/client_room.cpp b/src/citra_qt/multiplayer/client_room.cpp
index 2fff32275..8e37426bd 100644
--- a/src/citra_qt/multiplayer/client_room.cpp
+++ b/src/citra_qt/multiplayer/client_room.cpp
@@ -15,6 +15,7 @@
 #include "citra_qt/multiplayer/message.h"
 #include "common/logging/log.h"
 #include "core/announce_multiplayer_session.h"
+#include "ui_client_room.h"
 
 ClientRoomWindow::ClientRoomWindow(QWidget* parent)
     : QDialog(parent, Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint),
@@ -41,6 +42,8 @@ ClientRoomWindow::ClientRoomWindow(QWidget* parent)
     UpdateView();
 }
 
+ClientRoomWindow::~ClientRoomWindow() = default;
+
 void ClientRoomWindow::OnRoomUpdate(const Network::RoomInformation& info) {
     UpdateView();
 }
diff --git a/src/citra_qt/multiplayer/client_room.h b/src/citra_qt/multiplayer/client_room.h
index f235c4b77..960dbe97f 100644
--- a/src/citra_qt/multiplayer/client_room.h
+++ b/src/citra_qt/multiplayer/client_room.h
@@ -5,13 +5,17 @@
 #pragma once
 
 #include "citra_qt/multiplayer/chat_room.h"
-#include "ui_client_room.h"
+
+namespace Ui {
+class ClientRoom;
+}
 
 class ClientRoomWindow : public QDialog {
     Q_OBJECT
 
 public:
     explicit ClientRoomWindow(QWidget* parent);
+    ~ClientRoomWindow();
 
 public slots:
     void OnRoomUpdate(const Network::RoomInformation&);
diff --git a/src/citra_qt/multiplayer/direct_connect.cpp b/src/citra_qt/multiplayer/direct_connect.cpp
index d623054dd..7a47918fb 100644
--- a/src/citra_qt/multiplayer/direct_connect.cpp
+++ b/src/citra_qt/multiplayer/direct_connect.cpp
@@ -17,6 +17,7 @@
 #include "citra_qt/ui_settings.h"
 #include "core/settings.h"
 #include "network/network.h"
+#include "ui_direct_connect.h"
 
 enum class ConnectionType : u8 { TraversalServer, IP };
 
@@ -30,11 +31,11 @@ DirectConnectWindow::DirectConnectWindow(QWidget* parent)
     watcher = new QFutureWatcher<void>;
     connect(watcher, &QFutureWatcher<void>::finished, this, &DirectConnectWindow::OnConnection);
 
-    ui->nickname->setValidator(Validation::get().nickname);
+    ui->nickname->setValidator(validation.GetNickname());
     ui->nickname->setText(UISettings::values.nickname);
-    ui->ip->setValidator(Validation::get().ip);
+    ui->ip->setValidator(validation.GetIP());
     ui->ip->setText(UISettings::values.ip);
-    ui->port->setValidator(Validation::get().port);
+    ui->port->setValidator(validation.GetPort());
     ui->port->setText(UISettings::values.port);
 
     // TODO(jroweboy): Show or hide the connection options based on the current value of the combo
@@ -42,6 +43,8 @@ DirectConnectWindow::DirectConnectWindow(QWidget* parent)
     connect(ui->connect, &QPushButton::pressed, this, &DirectConnectWindow::Connect);
 }
 
+DirectConnectWindow::~DirectConnectWindow() = default;
+
 void DirectConnectWindow::Connect() {
     if (!ui->nickname->hasAcceptableInput()) {
         NetworkMessage::ShowError(NetworkMessage::USERNAME_NOT_VALID);
diff --git a/src/citra_qt/multiplayer/direct_connect.h b/src/citra_qt/multiplayer/direct_connect.h
index 86259dc3b..de167c1f9 100644
--- a/src/citra_qt/multiplayer/direct_connect.h
+++ b/src/citra_qt/multiplayer/direct_connect.h
@@ -7,13 +7,18 @@
 #include <memory>
 #include <QDialog>
 #include <QFutureWatcher>
-#include "ui_direct_connect.h"
+#include "citra_qt/multiplayer/validation.h"
+
+namespace Ui {
+class DirectConnect;
+}
 
 class DirectConnectWindow : public QDialog {
     Q_OBJECT
 
 public:
     explicit DirectConnectWindow(QWidget* parent = nullptr);
+    ~DirectConnectWindow();
 
 signals:
     /**
@@ -32,4 +37,5 @@ private:
 
     QFutureWatcher<void>* watcher;
     std::unique_ptr<Ui::DirectConnect> ui;
+    Validation validation;
 };
diff --git a/src/citra_qt/multiplayer/host_room.cpp b/src/citra_qt/multiplayer/host_room.cpp
index e8fbd44f8..3f53b3c8a 100644
--- a/src/citra_qt/multiplayer/host_room.cpp
+++ b/src/citra_qt/multiplayer/host_room.cpp
@@ -20,6 +20,7 @@
 #include "common/logging/log.h"
 #include "core/announce_multiplayer_session.h"
 #include "core/settings.h"
+#include "ui_host_room.h"
 
 HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list,
                                std::shared_ptr<Core::AnnounceMultiplayerSession> session)
@@ -28,9 +29,9 @@ HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list,
     ui->setupUi(this);
 
     // set up validation for all of the fields
-    ui->room_name->setValidator(Validation::get().room_name);
-    ui->username->setValidator(Validation::get().nickname);
-    ui->port->setValidator(Validation::get().port);
+    ui->room_name->setValidator(validation.GetRoomName());
+    ui->username->setValidator(validation.GetNickname());
+    ui->port->setValidator(validation.GetPort());
     ui->port->setPlaceholderText(QString::number(Network::DefaultRoomPort));
 
     // Create a proxy to the game list to display the list of preferred games
@@ -57,6 +58,8 @@ HostRoomWindow::HostRoomWindow(QWidget* parent, QStandardItemModel* list,
     }
 }
 
+HostRoomWindow::~HostRoomWindow() = default;
+
 void HostRoomWindow::Host() {
     if (!ui->username->hasAcceptableInput()) {
         NetworkMessage::ShowError(NetworkMessage::USERNAME_NOT_VALID);
diff --git a/src/citra_qt/multiplayer/host_room.h b/src/citra_qt/multiplayer/host_room.h
index 53362ddba..038b9f538 100644
--- a/src/citra_qt/multiplayer/host_room.h
+++ b/src/citra_qt/multiplayer/host_room.h
@@ -10,8 +10,12 @@
 #include <QStandardItemModel>
 #include <QVariant>
 #include "citra_qt/multiplayer/chat_room.h"
+#include "citra_qt/multiplayer/validation.h"
 #include "network/network.h"
-#include "ui_host_room.h"
+
+namespace Ui {
+class HostRoom;
+}
 
 namespace Core {
 class AnnounceMultiplayerSession;
@@ -28,6 +32,7 @@ class HostRoomWindow : public QDialog {
 public:
     explicit HostRoomWindow(QWidget* parent, QStandardItemModel* list,
                             std::shared_ptr<Core::AnnounceMultiplayerSession> session);
+    ~HostRoomWindow();
 
 signals:
     /**
@@ -50,6 +55,7 @@ private:
     QStandardItemModel* game_list;
     ComboBoxProxyModel* proxy;
     std::unique_ptr<Ui::HostRoom> ui;
+    Validation validation;
 };
 
 /**
diff --git a/src/citra_qt/multiplayer/lobby.cpp b/src/citra_qt/multiplayer/lobby.cpp
index e4522af22..1c90ef4ae 100644
--- a/src/citra_qt/multiplayer/lobby.cpp
+++ b/src/citra_qt/multiplayer/lobby.cpp
@@ -47,7 +47,7 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
     ui->room_list->setExpandsOnDoubleClick(false);
     ui->room_list->setContextMenuPolicy(Qt::CustomContextMenu);
 
-    ui->nickname->setValidator(Validation::get().nickname);
+    ui->nickname->setValidator(validation.GetNickname());
     ui->nickname->setText(UISettings::values.nickname);
 
     // UI Buttons
@@ -189,7 +189,6 @@ void Lobby::OnRefreshLobby() {
             first_item->appendRow(new LobbyItemExpandedMemberList(members));
         }
     }
-    proxy->setSourceModel(model);
 
     // Reenable the refresh button and resize the columns
     ui->refresh_list->setEnabled(true);
@@ -200,10 +199,10 @@ void Lobby::OnRefreshLobby() {
     }
 
     // Set the member list child items to span all columns
-    for (int i = 0; i < model->rowCount(); i++) {
+    for (int i = 0; i < proxy->rowCount(); i++) {
         auto parent = model->item(i, 0);
         if (parent->hasChildren()) {
-            ui->room_list->setFirstColumnSpanned(0, parent->index(), true);
+            ui->room_list->setFirstColumnSpanned(0, proxy->index(i, 0), true);
         }
     }
 }
diff --git a/src/citra_qt/multiplayer/lobby.h b/src/citra_qt/multiplayer/lobby.h
index 80c81a3a0..d3f753fcd 100644
--- a/src/citra_qt/multiplayer/lobby.h
+++ b/src/citra_qt/multiplayer/lobby.h
@@ -10,6 +10,7 @@
 #include <QFutureWatcher>
 #include <QSortFilterProxyModel>
 #include <QStandardItemModel>
+#include "citra_qt/multiplayer/validation.h"
 #include "common/announce_multiplayer_room.h"
 #include "core/announce_multiplayer_session.h"
 #include "network/network.h"
@@ -104,6 +105,7 @@ private:
     std::weak_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
     std::unique_ptr<Ui::Lobby> ui;
     QFutureWatcher<void>* watcher;
+    Validation validation;
 };
 
 /**
diff --git a/src/citra_qt/multiplayer/validation.h b/src/citra_qt/multiplayer/validation.h
index 19c8fca75..4e8f6b9e9 100644
--- a/src/citra_qt/multiplayer/validation.h
+++ b/src/citra_qt/multiplayer/validation.h
@@ -9,36 +9,40 @@
 
 class Validation {
 public:
-    static Validation get() {
-        static Validation validation;
-        return validation;
-    }
-
-    ~Validation() {
-        delete room_name;
-        delete nickname;
-        delete ip;
-        delete port;
+    Validation()
+        : room_name(room_name_regex), nickname(nickname_regex), ip(ip_regex), port(0, 65535) {}
+
+    ~Validation() = default;
+
+    const QValidator* GetRoomName() const {
+        return &room_name;
+    }
+    const QValidator* GetNickname() const {
+        return &nickname;
+    }
+    const QValidator* GetIP() const {
+        return &ip;
+    }
+    const QValidator* GetPort() const {
+        return &port;
     }
 
+private:
     /// room name can be alphanumeric and " " "_" "." and "-"
     QRegExp room_name_regex = QRegExp("^[a-zA-Z0-9._- ]+$");
-    const QValidator* room_name = new QRegExpValidator(room_name_regex);
+    QRegExpValidator room_name;
 
     /// nickname can be alphanumeric and " " "_" "." and "-"
     QRegExp nickname_regex = QRegExp("^[a-zA-Z0-9._- ]+$");
-    const QValidator* nickname = new QRegExpValidator(nickname_regex);
+    QRegExpValidator nickname;
 
     /// ipv4 address only
     // TODO remove this when we support hostnames in direct connect
     QRegExp ip_regex = QRegExp(
         "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|"
         "2[0-4][0-9]|25[0-5])");
-    const QValidator* ip = new QRegExpValidator(ip_regex);
+    QRegExpValidator ip;
 
     /// port must be between 0 and 65535
-    const QValidator* port = new QIntValidator(0, 65535);
-
-private:
-    Validation() = default;
+    QIntValidator port;
 };