diff --git a/src/citra_qt/CMakeLists.txt b/src/citra_qt/CMakeLists.txt index 699e7006b..1a150065f 100644 --- a/src/citra_qt/CMakeLists.txt +++ b/src/citra_qt/CMakeLists.txt @@ -69,6 +69,8 @@ add_executable(citra-qt multiplayer/lobby.cpp multiplayer/message.h multiplayer/message.cpp + multiplayer/state.cpp + multiplayer/state.h multiplayer/validation.h ui_settings.cpp ui_settings.h diff --git a/src/citra_qt/main.cpp b/src/citra_qt/main.cpp index 47bc73d90..75d1fb0fb 100644 --- a/src/citra_qt/main.cpp +++ b/src/citra_qt/main.cpp @@ -31,11 +31,7 @@ #include "citra_qt/game_list.h" #include "citra_qt/hotkeys.h" #include "citra_qt/main.h" -#include "citra_qt/multiplayer/client_room.h" -#include "citra_qt/multiplayer/direct_connect.h" -#include "citra_qt/multiplayer/host_room.h" -#include "citra_qt/multiplayer/lobby.h" -#include "citra_qt/multiplayer/message.h" +#include "citra_qt/multiplayer/state.h" #include "citra_qt/ui_settings.h" #include "citra_qt/updater/updater.h" #include "citra_qt/util/clickable_label.h" @@ -137,16 +133,6 @@ GMainWindow::GMainWindow() : config(new Config()), emu_thread(nullptr) { Network::Init(); - if (auto member = Network::GetRoomMember().lock()) { - // register the network structs to use in slots and signals - qRegisterMetaType(); - state_callback_handle = member->BindOnStateChanged( - [this](const Network::RoomMember::State& state) { emit NetworkStateChanged(state); }); - connect(this, &GMainWindow::NetworkStateChanged, this, &GMainWindow::OnNetworkStateChanged); - } - - qRegisterMetaType(); - setWindowTitle(QString("Citra %1| %2-%3") .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); show(); @@ -173,12 +159,6 @@ GMainWindow::~GMainWindow() { delete render_window; Pica::g_debug_context.reset(); - - if (state_callback_handle) { - if (auto member = Network::GetRoomMember().lock()) { - member->Unbind(state_callback_handle); - } - } Network::Shutdown(); } @@ -192,6 +172,8 @@ void GMainWindow::InitializeWidgets() { game_list = new GameList(this); ui.horizontalLayout->addWidget(game_list); + multiplayer_state = new MultiplayerState(this, game_list->GetModel()); + // Setup updater updater = new Updater(this); UISettings::values.updater_found = updater->HasUpdater(); @@ -220,24 +202,14 @@ void GMainWindow::InitializeWidgets() { tr("Time taken to emulate a 3DS frame, not counting framelimiting or v-sync. For " "full-speed emulation this should be at most 16.67 ms.")); - announce_multiplayer_session = std::make_shared(); - announce_multiplayer_session->BindErrorCallback( - [this](const Common::WebResult& result) { emit AnnounceFailed(result); }); - connect(this, &GMainWindow::AnnounceFailed, this, &GMainWindow::OnAnnounceFailed); - network_status_text = new ClickableLabel(this); - network_status_icon = new ClickableLabel(this); - network_status_text->setToolTip(tr("Current connection status")); - for (auto& label : {emu_speed_label, game_fps_label, emu_frametime_label}) { label->setVisible(false); label->setFrameStyle(QFrame::NoFrame); label->setContentsMargins(4, 0, 4, 0); statusBar()->addPermanentWidget(label, 0); } - statusBar()->addPermanentWidget(network_status_text, 0); - statusBar()->addPermanentWidget(network_status_icon, 0); - network_status_icon->setPixmap(QIcon::fromTheme("disconnected").pixmap(16)); - network_status_text->setText(tr("Not Connected. Click here to find a room!")); + statusBar()->addPermanentWidget(multiplayer_state->GetStatusText(), 0); + statusBar()->addPermanentWidget(multiplayer_state->GetStatusIcon(), 0); statusBar()->setVisible(true); // Removes an ugly inner border from the status bar widgets under Linux @@ -431,9 +403,6 @@ void GMainWindow::ConnectWidgetEvents() { connect(this, &GMainWindow::UpdateProgress, this, &GMainWindow::OnUpdateProgress); connect(this, &GMainWindow::CIAInstallReport, this, &GMainWindow::OnCIAInstallReport); connect(this, &GMainWindow::CIAInstallFinished, this, &GMainWindow::OnCIAInstallFinished); - - connect(network_status_text, &ClickableLabel::clicked, this, &GMainWindow::OnOpenNetworkRoom); - connect(network_status_icon, &ClickableLabel::clicked, this, &GMainWindow::OnOpenNetworkRoom); } void GMainWindow::ConnectMenuEvents() { @@ -462,12 +431,16 @@ void GMainWindow::ConnectMenuEvents() { connect(ui.action_Show_Status_Bar, &QAction::triggered, statusBar(), &QStatusBar::setVisible); // Multiplayer - connect(ui.action_View_Lobby, &QAction::triggered, this, &GMainWindow::OnViewLobby); - connect(ui.action_Start_Room, &QAction::triggered, this, &GMainWindow::OnCreateRoom); - connect(ui.action_Stop_Room, &QAction::triggered, this, &GMainWindow::OnCloseRoom); - connect(ui.action_Connect_To_Room, &QAction::triggered, this, - &GMainWindow::OnDirectConnectToRoom); - connect(ui.action_Chat, &QAction::triggered, this, &GMainWindow::OnOpenNetworkRoom); + connect(ui.action_View_Lobby, &QAction::triggered, multiplayer_state, + &MultiplayerState::OnViewLobby); + connect(ui.action_Start_Room, &QAction::triggered, multiplayer_state, + &MultiplayerState::OnCreateRoom); + connect(ui.action_Stop_Room, &QAction::triggered, multiplayer_state, + &MultiplayerState::OnCloseRoom); + connect(ui.action_Connect_To_Room, &QAction::triggered, multiplayer_state, + &MultiplayerState::OnDirectConnectToRoom); + connect(ui.action_Chat, &QAction::triggered, multiplayer_state, + &MultiplayerState::OnOpenNetworkRoom); ui.action_Fullscreen->setShortcut(GetHotkey("Main Window", "Fullscreen", this)->key()); ui.action_Screen_Layout_Swap_Screens->setShortcut( @@ -931,30 +904,6 @@ void GMainWindow::OnMenuRecentFile() { } } -void GMainWindow::OnNetworkStateChanged(const Network::RoomMember::State& state) { - LOG_INFO(Frontend, "network state change"); - if (state == Network::RoomMember::State::Joined) { - network_status_icon->setPixmap(QIcon::fromTheme("connected").pixmap(16)); - network_status_text->setText(tr("Connected")); - ui.action_Chat->setEnabled(true); - return; - } - network_status_icon->setPixmap(QIcon::fromTheme("disconnected").pixmap(16)); - network_status_text->setText(tr("Not Connected")); - ui.action_Chat->setDisabled(true); - - ChangeRoomState(); -} - -void GMainWindow::OnAnnounceFailed(const Common::WebResult& result) { - announce_multiplayer_session->Stop(); - QMessageBox::warning( - this, tr("Error"), - tr("Announcing the room failed.\nThe room will not get listed publicly.\nError: ") + - QString::fromStdString(result.result_string), - QMessageBox::Ok); -} - void GMainWindow::OnStartGame() { emu_thread->SetRunning(true); qRegisterMetaType("Core::System::ResultStatus"); @@ -1129,80 +1078,6 @@ void GMainWindow::OnCreateGraphicsSurfaceViewer() { graphicsSurfaceViewerWidget->show(); } -static void BringWidgetToFront(QWidget* widget) { - widget->show(); - widget->activateWindow(); - widget->raise(); -} - -void GMainWindow::OnViewLobby() { - if (lobby == nullptr) { - lobby = new Lobby(this, game_list->GetModel(), announce_multiplayer_session); - connect(lobby, &Lobby::Closed, [&] { - LOG_INFO(Frontend, "Destroying lobby"); - // lobby->close(); - lobby = nullptr; - }); - } - BringWidgetToFront(lobby); -} - -void GMainWindow::OnCreateRoom() { - if (host_room == nullptr) { - host_room = new HostRoomWindow(this, game_list->GetModel(), announce_multiplayer_session); - connect(host_room, &HostRoomWindow::Closed, [&] { - // host_room->close(); - LOG_INFO(Frontend, "Destroying host room"); - host_room = nullptr; - }); - } - BringWidgetToFront(host_room); -} - -void GMainWindow::OnCloseRoom() { - if (auto room = Network::GetRoom().lock()) { - if (room->GetState() == Network::Room::State::Open) { - if (NetworkMessage::WarnCloseRoom()) { - room->Destroy(); - announce_multiplayer_session->Stop(); - // host_room->close(); - } - } - } -} - -void GMainWindow::OnOpenNetworkRoom() { - if (auto member = Network::GetRoomMember().lock()) { - if (member->IsConnected()) { - if (client_room == nullptr) { - client_room = new ClientRoomWindow(this); - connect(client_room, &ClientRoomWindow::Closed, [&] { - LOG_INFO(Frontend, "Destroying client room"); - // client_room->close(); - client_room = nullptr; - }); - } - BringWidgetToFront(client_room); - return; - } - } - // If the user is not a member of a room, show the lobby instead. - // This is currently only used on the clickable label in the status bar - OnViewLobby(); -} - -void GMainWindow::OnDirectConnectToRoom() { - if (direct_connect == nullptr) { - direct_connect = new DirectConnectWindow(this); - connect(direct_connect, &DirectConnectWindow::Closed, [&] { - LOG_INFO(Frontend, "Destroying direct connect"); - // direct_connect->close(); - direct_connect = nullptr; - }); - } - BringWidgetToFront(direct_connect); -} - void GMainWindow::UpdateStatusBar() { if (emu_thread == nullptr) { status_bar_update_timer.stop(); @@ -1335,17 +1210,7 @@ void GMainWindow::closeEvent(QCloseEvent* event) { ShutdownGame(); render_window->close(); - - // Close Multiplayer windows - if (host_room) - host_room->close(); - if (direct_connect) - direct_connect->close(); - if (client_room) - client_room->close(); - if (lobby) - lobby->close(); - + multiplayer_state->Close(); QWidget::closeEvent(event); } diff --git a/src/citra_qt/main.h b/src/citra_qt/main.h index 27aad35ca..a3f2371fa 100644 --- a/src/citra_qt/main.h +++ b/src/citra_qt/main.h @@ -29,6 +29,7 @@ class GraphicsTracingWidget; class GraphicsVertexShaderWidget; class GRenderWindow; class MicroProfileDialog; +class MultiplayerState; class ProfilerWidget; template class QFutureWatcher; @@ -37,16 +38,6 @@ class RegistersWidget; class Updater; class WaitTreeWidget; -// Multiplayer forward declarations -class Lobby; -class HostRoomWindow; -class ClientRoomWindow; -class DirectConnectWindow; - -namespace Core { -class AnnounceMultiplayerSession; -} - class GMainWindow : public QMainWindow { Q_OBJECT @@ -94,16 +85,6 @@ signals: // Signal that tells widgets to update icons to use the current theme void UpdateThemedIcons(); - void NetworkStateChanged(const Network::RoomMember::State&); - void AnnounceFailed(const Common::WebResult&); - -public slots: - void OnViewLobby(); - void OnCreateRoom(); - void OnCloseRoom(); - void OnOpenNetworkRoom(); - void OnDirectConnectToRoom(); - private: void InitializeWidgets(); void InitializeDebugWidgets(); @@ -173,8 +154,6 @@ private slots: /// Called whenever a user selects the "File->Select Game List Root" menu item void OnMenuSelectGameListRoot(); void OnMenuRecentFile(); - void OnNetworkStateChanged(const Network::RoomMember::State& state); - void OnAnnounceFailed(const Common::WebResult&); void OnConfigure(); void OnToggleFilterBar(); void OnDisplayTitleBars(bool); @@ -211,12 +190,10 @@ private: QLabel* emu_speed_label = nullptr; QLabel* game_fps_label = nullptr; QLabel* emu_frametime_label = nullptr; - ClickableLabel* network_status_icon = nullptr; - ClickableLabel* network_status_text = nullptr; QTimer status_bar_update_timer; + MultiplayerState* multiplayer_state = nullptr; std::unique_ptr config; - std::shared_ptr announce_multiplayer_session; // Whether emulation is currently running in Citra. bool emulation_running = false; @@ -237,14 +214,6 @@ private: bool explicit_update_check = false; bool defer_update_prompt = false; - // Multiplayer windows - Lobby* lobby = nullptr; - HostRoomWindow* host_room = nullptr; - ClientRoomWindow* client_room = nullptr; - DirectConnectWindow* direct_connect = nullptr; - - Network::RoomMember::CallbackHandle state_callback_handle; - QAction* actions_recent_files[max_recent_files_item]; QTranslator translator; @@ -260,4 +229,3 @@ protected: Q_DECLARE_METATYPE(size_t); Q_DECLARE_METATYPE(Service::AM::InstallStatus); -Q_DECLARE_METATYPE(Common::WebResult); diff --git a/src/citra_qt/multiplayer/direct_connect.cpp b/src/citra_qt/multiplayer/direct_connect.cpp index 9d68d96d1..785062d48 100644 --- a/src/citra_qt/multiplayer/direct_connect.cpp +++ b/src/citra_qt/multiplayer/direct_connect.cpp @@ -12,6 +12,7 @@ #include "citra_qt/multiplayer/client_room.h" #include "citra_qt/multiplayer/direct_connect.h" #include "citra_qt/multiplayer/message.h" +#include "citra_qt/multiplayer/state.h" #include "citra_qt/multiplayer/validation.h" #include "citra_qt/ui_settings.h" #include "core/settings.h" @@ -124,7 +125,7 @@ void DirectConnectWindow::OnConnection() { ShowError(NetworkMessage::USERNAME_IN_USE); break; case Network::RoomMember::State::Joining: - auto parent = static_cast(parentWidget()); + auto parent = static_cast(parentWidget()); parent->OnOpenNetworkRoom(); close(); } diff --git a/src/citra_qt/multiplayer/host_room.cpp b/src/citra_qt/multiplayer/host_room.cpp index 02122f445..df43b23b2 100644 --- a/src/citra_qt/multiplayer/host_room.cpp +++ b/src/citra_qt/multiplayer/host_room.cpp @@ -14,6 +14,7 @@ #include "citra_qt/main.h" #include "citra_qt/multiplayer/host_room.h" #include "citra_qt/multiplayer/message.h" +#include "citra_qt/multiplayer/state.h" #include "citra_qt/multiplayer/validation.h" #include "citra_qt/ui_settings.h" #include "common/logging/log.h" @@ -136,8 +137,8 @@ void HostRoomWindow::OnConnection() { LOG_ERROR(Network, "Starting announce session failed"); } } - auto parent = static_cast(parentWidget()); - parent->ChangeRoomState(); + auto parent = static_cast(parentWidget()); + // parent->ChangeRoomState(); parent->OnOpenNetworkRoom(); close(); emit Closed(); diff --git a/src/citra_qt/multiplayer/lobby.cpp b/src/citra_qt/multiplayer/lobby.cpp index c20c7d59f..3e21738c2 100644 --- a/src/citra_qt/multiplayer/lobby.cpp +++ b/src/citra_qt/multiplayer/lobby.cpp @@ -11,6 +11,7 @@ #include "citra_qt/multiplayer/lobby.h" #include "citra_qt/multiplayer/lobby_p.h" #include "citra_qt/multiplayer/message.h" +#include "citra_qt/multiplayer/state.h" #include "citra_qt/multiplayer/validation.h" #include "citra_qt/ui_settings.h" #include "common/logging/log.h" @@ -51,9 +52,9 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list, ui->nickname->setText(UISettings::values.nickname); // UI Buttons - GMainWindow* p = reinterpret_cast(parent); + MultiplayerState* p = reinterpret_cast(parent); connect(ui->refresh_list, &QPushButton::pressed, this, &Lobby::RefreshLobby); - connect(ui->chat, &QPushButton::pressed, p, &GMainWindow::OnOpenNetworkRoom); + connect(ui->chat, &QPushButton::pressed, p, &MultiplayerState::OnOpenNetworkRoom); connect(ui->games_owned, &QCheckBox::stateChanged, proxy, &LobbyFilterProxyModel::SetFilterOwned); connect(ui->hide_full, &QCheckBox::stateChanged, proxy, &LobbyFilterProxyModel::SetFilterFull); @@ -64,7 +65,7 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list, // Actions connect(this, &Lobby::LobbyRefreshed, this, &Lobby::OnRefreshLobby); // TODO(jroweboy): change this slot to OnConnected? - connect(this, &Lobby::Connected, p, &GMainWindow::OnOpenNetworkRoom); + connect(this, &Lobby::Connected, p, &MultiplayerState::OnOpenNetworkRoom); // setup the callbacks for network updates if (auto member = Network::GetRoomMember().lock()) { @@ -90,8 +91,6 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list, ui->chat->setDisabled(true); } -Lobby::~Lobby() {} - const QString Lobby::PasswordPrompt() { bool ok; const QString text = @@ -305,7 +304,7 @@ void Lobby::OnConnection() { ShowError(NetworkMessage::UNABLE_TO_CONNECT); break; case Network::RoomMember::State::Joining: - auto parent = static_cast(parentWidget()); + auto parent = static_cast(parentWidget()); parent->OnOpenNetworkRoom(); close(); break; diff --git a/src/citra_qt/multiplayer/lobby.h b/src/citra_qt/multiplayer/lobby.h index c8ec502f9..d2141b6ca 100644 --- a/src/citra_qt/multiplayer/lobby.h +++ b/src/citra_qt/multiplayer/lobby.h @@ -31,7 +31,7 @@ class Lobby : public QDialog { public: explicit Lobby(QWidget* parent, QStandardItemModel* list, std::shared_ptr session); - ~Lobby(); + ~Lobby() = default; public slots: /** diff --git a/src/citra_qt/multiplayer/state.cpp b/src/citra_qt/multiplayer/state.cpp new file mode 100644 index 000000000..3b072f85c --- /dev/null +++ b/src/citra_qt/multiplayer/state.cpp @@ -0,0 +1,157 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include +#include +#include +#include "citra_qt/game_list.h" +#include "citra_qt/multiplayer/client_room.h" +#include "citra_qt/multiplayer/direct_connect.h" +#include "citra_qt/multiplayer/host_room.h" +#include "citra_qt/multiplayer/lobby.h" +#include "citra_qt/multiplayer/message.h" +#include "citra_qt/multiplayer/state.h" +#include "citra_qt/util/clickable_label.h" +#include "common/announce_multiplayer_room.h" +#include "common/logging/log.h" + +MultiplayerState::MultiplayerState(QWidget* parent, QStandardItemModel* game_list_model) + : QWidget(parent), game_list_model(game_list_model) { + if (auto member = Network::GetRoomMember().lock()) { + // register the network structs to use in slots and signals + qRegisterMetaType(); + state_callback_handle = member->BindOnStateChanged( + [this](const Network::RoomMember::State& state) { emit NetworkStateChanged(state); }); + connect(this, &MultiplayerState::NetworkStateChanged, this, + &MultiplayerState::OnNetworkStateChanged); + } + + qRegisterMetaType(); + announce_multiplayer_session = std::make_shared(); + announce_multiplayer_session->BindErrorCallback( + [this](const Common::WebResult& result) { emit AnnounceFailed(result); }); + connect(this, &MultiplayerState::AnnounceFailed, this, &MultiplayerState::OnAnnounceFailed); + + status_text = new ClickableLabel(this); + status_icon = new ClickableLabel(this); + status_text->setToolTip(tr("Current connection status")); + status_text->setText(tr("Not Connected. Click here to find a room!")); + status_icon->setPixmap(QIcon::fromTheme("disconnected").pixmap(16)); + + connect(status_text, &ClickableLabel::clicked, this, &MultiplayerState::OnOpenNetworkRoom); + connect(status_icon, &ClickableLabel::clicked, this, &MultiplayerState::OnOpenNetworkRoom); +} + +MultiplayerState::~MultiplayerState() { + if (state_callback_handle) { + if (auto member = Network::GetRoomMember().lock()) { + member->Unbind(state_callback_handle); + } + } +} + +void MultiplayerState::Close() { + if (host_room) + host_room->close(); + if (direct_connect) + direct_connect->close(); + if (client_room) + client_room->close(); + if (lobby) + lobby->close(); +} + +void MultiplayerState::OnNetworkStateChanged(const Network::RoomMember::State& state) { + NGLOG_DEBUG(Frontend, "Network state change"); + if (state == Network::RoomMember::State::Joined) { + status_icon->setPixmap(QIcon::fromTheme("connected").pixmap(16)); + status_text->setText(tr("Connected")); + return; + } + status_icon->setPixmap(QIcon::fromTheme("disconnected").pixmap(16)); + status_text->setText(tr("Not Connected")); +} + +void MultiplayerState::OnAnnounceFailed(const Common::WebResult& result) { + announce_multiplayer_session->Stop(); + QMessageBox::warning(this, tr("Error"), + tr("Failed to announce the room to the public lobby.\nThe room will not " + "get listed publicly.\nError: ") + + QString::fromStdString(result.result_string), + QMessageBox::Ok); +} + +static void BringWidgetToFront(QWidget* widget) { + widget->show(); + widget->activateWindow(); + widget->raise(); +} + +void MultiplayerState::OnViewLobby() { + if (lobby == nullptr) { + lobby = new Lobby(this, game_list_model, announce_multiplayer_session); + connect(lobby, &Lobby::Closed, [&] { + LOG_INFO(Frontend, "Destroying lobby"); + // lobby->close(); + lobby = nullptr; + }); + } + BringWidgetToFront(lobby); +} + +void MultiplayerState::OnCreateRoom() { + if (host_room == nullptr) { + host_room = new HostRoomWindow(this, game_list_model, announce_multiplayer_session); + connect(host_room, &HostRoomWindow::Closed, [&] { + // host_room->close(); + LOG_INFO(Frontend, "Destroying host room"); + host_room = nullptr; + }); + } + BringWidgetToFront(host_room); +} + +void MultiplayerState::OnCloseRoom() { + if (auto room = Network::GetRoom().lock()) { + if (room->GetState() == Network::Room::State::Open) { + if (NetworkMessage::WarnCloseRoom()) { + room->Destroy(); + announce_multiplayer_session->Stop(); + // host_room->close(); + } + } + } +} + +void MultiplayerState::OnOpenNetworkRoom() { + if (auto member = Network::GetRoomMember().lock()) { + if (member->IsConnected()) { + if (client_room == nullptr) { + client_room = new ClientRoomWindow(this); + connect(client_room, &ClientRoomWindow::Closed, [&] { + LOG_INFO(Frontend, "Destroying client room"); + // client_room->close(); + client_room = nullptr; + }); + } + BringWidgetToFront(client_room); + return; + } + } + // If the user is not a member of a room, show the lobby instead. + // This is currently only used on the clickable label in the status bar + OnViewLobby(); +} + +void MultiplayerState::OnDirectConnectToRoom() { + if (direct_connect == nullptr) { + direct_connect = new DirectConnectWindow(this); + connect(direct_connect, &DirectConnectWindow::Closed, [&] { + LOG_INFO(Frontend, "Destroying direct connect"); + // direct_connect->close(); + direct_connect = nullptr; + }); + } + BringWidgetToFront(direct_connect); +} diff --git a/src/citra_qt/multiplayer/state.h b/src/citra_qt/multiplayer/state.h new file mode 100644 index 000000000..7bfff6d4e --- /dev/null +++ b/src/citra_qt/multiplayer/state.h @@ -0,0 +1,65 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include "network/network.h" + +class QStandardItemModel; +class Lobby; +class HostRoomWindow; +class ClientRoomWindow; +class DirectConnectWindow; +class ClickableLabel; +namespace Core { +class AnnounceMultiplayerSession; +} + +class MultiplayerState : public QWidget { + Q_OBJECT; + +public: + explicit MultiplayerState(QWidget* parent, QStandardItemModel* game_list); + ~MultiplayerState(); + + /** + * Close all open multiplayer related dialogs + */ + void Close(); + + ClickableLabel* GetStatusText() const { + return status_text; + } + + ClickableLabel* GetStatusIcon() const { + return status_icon; + } + +public slots: + void OnNetworkStateChanged(const Network::RoomMember::State& state); + void OnViewLobby(); + void OnCreateRoom(); + void OnCloseRoom(); + void OnOpenNetworkRoom(); + void OnDirectConnectToRoom(); + void OnAnnounceFailed(const Common::WebResult&); + +signals: + void NetworkStateChanged(const Network::RoomMember::State&); + void AnnounceFailed(const Common::WebResult&); + +private: + Lobby* lobby = nullptr; + HostRoomWindow* host_room = nullptr; + ClientRoomWindow* client_room = nullptr; + DirectConnectWindow* direct_connect = nullptr; + ClickableLabel* status_icon = nullptr; + ClickableLabel* status_text = nullptr; + QStandardItemModel* game_list_model = nullptr; + std::shared_ptr announce_multiplayer_session; + Network::RoomMember::CallbackHandle state_callback_handle; +}; + +Q_DECLARE_METATYPE(Common::WebResult);