1 // Copyright 2017 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #pragma once
6 
7 #include <memory>
8 #include <QDialog>
9 #include <QFutureWatcher>
10 #include <QSortFilterProxyModel>
11 #include <QStandardItemModel>
12 #include "citra_qt/multiplayer/validation.h"
13 #include "common/announce_multiplayer_room.h"
14 #include "core/announce_multiplayer_session.h"
15 #include "network/network.h"
16 
17 namespace Ui {
18 class Lobby;
19 }
20 
21 class LobbyModel;
22 class LobbyFilterProxyModel;
23 
24 /**
25  * Listing of all public games pulled from services. The lobby should be simple enough for users to
26  * find the game they want to play, and join it.
27  */
28 class Lobby : public QDialog {
29     Q_OBJECT
30 
31 public:
32     explicit Lobby(QWidget* parent, QStandardItemModel* list,
33                    std::shared_ptr<Core::AnnounceMultiplayerSession> session);
34     ~Lobby() override;
35 
36     /**
37      * Updates the lobby with a new game list model.
38      * This model should be the original model of the game list.
39      */
40     void UpdateGameList(QStandardItemModel* list);
41     void RetranslateUi();
42 
43 public slots:
44     /**
45      * Begin the process to pull the latest room list from web services. After the listing is
46      * returned from web services, `LobbyRefreshed` will be signalled
47      */
48     void RefreshLobby();
49 
50 private slots:
51     /**
52      * Pulls the list of rooms from network and fills out the lobby model with the results
53      */
54     void OnRefreshLobby();
55 
56     /**
57      * Handler for single clicking on a room in the list. Expands the treeitem to show player
58      * information for the people in the room
59      *
60      * index - The row of the proxy model that the user wants to join.
61      */
62     void OnExpandRoom(const QModelIndex&);
63 
64     /**
65      * Handler for double clicking on a room in the list. Gathers the host ip and port and attempts
66      * to connect. Will also prompt for a password in case one is required.
67      *
68      * index - The row of the proxy model that the user wants to join.
69      */
70     void OnJoinRoom(const QModelIndex&);
71 
72 signals:
73     void StateChanged(const Network::RoomMember::State&);
74 
75 private:
76     /**
77      * Removes all entries in the Lobby before refreshing.
78      */
79     void ResetModel();
80 
81     /**
82      * Prompts for a password. Returns an empty QString if the user either did not provide a
83      * password or if the user closed the window.
84      */
85     QString PasswordPrompt();
86 
87     std::unique_ptr<Ui::Lobby> ui;
88 
89     QStandardItemModel* model{};
90     QStandardItemModel* game_list{};
91     LobbyFilterProxyModel* proxy{};
92 
93     QFutureWatcher<AnnounceMultiplayerRoom::RoomList> room_list_watcher;
94     std::weak_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session;
95     QFutureWatcher<void>* watcher;
96     Validation validation;
97 };
98 
99 /**
100  * Proxy Model for filtering the lobby
101  */
102 class LobbyFilterProxyModel : public QSortFilterProxyModel {
103     Q_OBJECT;
104 
105 public:
106     explicit LobbyFilterProxyModel(QWidget* parent, QStandardItemModel* list);
107 
108     /**
109      * Updates the filter with a new game list model.
110      * This model should be the processed one created by the Lobby.
111      */
112     void UpdateGameList(QStandardItemModel* list);
113 
114     bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
115     void sort(int column, Qt::SortOrder order) override;
116 
117 public slots:
118     void SetFilterOwned(bool);
119     void SetFilterFull(bool);
120     void SetFilterSearch(const QString&);
121 
122 private:
123     QStandardItemModel* game_list;
124     bool filter_owned = false;
125     bool filter_full = false;
126     QString filter_search;
127 };
128