mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	citra_qt: Add a moderation dialog
The dialog currently supports accessing the ban list and removing entries from it.
This commit is contained in:
		
							parent
							
								
									7acd2664dd
								
							
						
					
					
						commit
						6359b6094c
					
				
					 9 changed files with 273 additions and 0 deletions
				
			
		|  | @ -99,6 +99,8 @@ add_executable(citra-qt | |||
|     multiplayer/lobby.cpp | ||||
|     multiplayer/message.h | ||||
|     multiplayer/message.cpp | ||||
|     multiplayer/moderation_dialog.cpp | ||||
|     multiplayer/moderation_dialog.h | ||||
|     multiplayer/state.cpp | ||||
|     multiplayer/state.h | ||||
|     multiplayer/validation.h | ||||
|  | @ -135,6 +137,7 @@ set(UIS | |||
|     multiplayer/chat_room.ui | ||||
|     multiplayer/client_room.ui | ||||
|     multiplayer/host_room.ui | ||||
|     multiplayer/moderation_dialog.ui | ||||
|     aboutdialog.ui | ||||
|     cheats.ui | ||||
|     hotkeys.ui | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ | |||
| #include "citra_qt/game_list_p.h" | ||||
| #include "citra_qt/multiplayer/client_room.h" | ||||
| #include "citra_qt/multiplayer/message.h" | ||||
| #include "citra_qt/multiplayer/moderation_dialog.h" | ||||
| #include "citra_qt/multiplayer/state.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "core/announce_multiplayer_session.h" | ||||
|  | @ -42,11 +43,23 @@ ClientRoomWindow::ClientRoomWindow(QWidget* parent) | |||
|     connect(ui->disconnect, &QPushButton::pressed, [this] { Disconnect(); }); | ||||
|     ui->disconnect->setDefault(false); | ||||
|     ui->disconnect->setAutoDefault(false); | ||||
|     connect(ui->moderation, &QPushButton::clicked, [this] { | ||||
|         ModerationDialog dialog(this); | ||||
|         dialog.exec(); | ||||
|     }); | ||||
|     ui->moderation->setDefault(false); | ||||
|     ui->moderation->setAutoDefault(false); | ||||
|     UpdateView(); | ||||
| } | ||||
| 
 | ||||
| ClientRoomWindow::~ClientRoomWindow() = default; | ||||
| 
 | ||||
| void ClientRoomWindow::SetModPerms(bool is_mod) { | ||||
|     ui->moderation->setVisible(is_mod); | ||||
|     ui->moderation->setDefault(false); | ||||
|     ui->moderation->setAutoDefault(false); | ||||
| } | ||||
| 
 | ||||
| void ClientRoomWindow::RetranslateUi() { | ||||
|     ui->retranslateUi(this); | ||||
|     ui->chat->RetranslateUi(); | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ public: | |||
|     ~ClientRoomWindow(); | ||||
| 
 | ||||
|     void RetranslateUi(); | ||||
|     void SetModPerms(bool is_mod); | ||||
| 
 | ||||
| public slots: | ||||
|     void OnRoomUpdate(const Network::RoomInformation&); | ||||
|  |  | |||
|  | @ -41,6 +41,16 @@ | |||
|          </property> | ||||
|         </spacer> | ||||
|        </item> | ||||
|        <item> | ||||
|         <widget class="QPushButton" name="moderation"> | ||||
|          <property name="text"> | ||||
|           <string>Moderation...</string> | ||||
|          </property> | ||||
|          <property name="visible"> | ||||
|           <bool>false</bool> | ||||
|          </property> | ||||
|         </widget> | ||||
|        </item> | ||||
|        <item> | ||||
|         <widget class="QPushButton" name="disconnect"> | ||||
|          <property name="text"> | ||||
|  |  | |||
							
								
								
									
										113
									
								
								src/citra_qt/multiplayer/moderation_dialog.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								src/citra_qt/multiplayer/moderation_dialog.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,113 @@ | |||
| // Copyright 2018 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <QStandardItem> | ||||
| #include <QStandardItemModel> | ||||
| #include "citra_qt/multiplayer/moderation_dialog.h" | ||||
| #include "network/network.h" | ||||
| #include "network/room_member.h" | ||||
| #include "ui_moderation_dialog.h" | ||||
| 
 | ||||
| namespace Column { | ||||
| enum { | ||||
|     SUBJECT, | ||||
|     TYPE, | ||||
|     COUNT, | ||||
| }; | ||||
| } | ||||
| 
 | ||||
| ModerationDialog::ModerationDialog(QWidget* parent) | ||||
|     : QDialog(parent), ui(std::make_unique<Ui::ModerationDialog>()) { | ||||
|     ui->setupUi(this); | ||||
| 
 | ||||
|     qRegisterMetaType<Network::Room::BanList>(); | ||||
| 
 | ||||
|     if (auto member = Network::GetRoomMember().lock()) { | ||||
|         callback_handle_status_message = member->BindOnStatusMessageReceived( | ||||
|             [this](const Network::StatusMessageEntry& status_message) { | ||||
|                 emit StatusMessageReceived(status_message); | ||||
|             }); | ||||
|         connect(this, &ModerationDialog::StatusMessageReceived, this, | ||||
|                 &ModerationDialog::OnStatusMessageReceived); | ||||
|         callback_handle_ban_list = member->BindOnBanListReceived( | ||||
|             [this](const Network::Room::BanList& ban_list) { emit BanListReceived(ban_list); }); | ||||
|         connect(this, &ModerationDialog::BanListReceived, this, &ModerationDialog::PopulateBanList); | ||||
|     } | ||||
| 
 | ||||
|     // Initialize the UI
 | ||||
|     model = new QStandardItemModel(ui->ban_list_view); | ||||
|     model->insertColumns(0, Column::COUNT); | ||||
|     model->setHeaderData(Column::SUBJECT, Qt::Horizontal, tr("Subject")); | ||||
|     model->setHeaderData(Column::TYPE, Qt::Horizontal, tr("Type")); | ||||
| 
 | ||||
|     ui->ban_list_view->setModel(model); | ||||
| 
 | ||||
|     // Load the ban list in background
 | ||||
|     LoadBanList(); | ||||
| 
 | ||||
|     connect(ui->refresh, &QPushButton::clicked, this, [this] { LoadBanList(); }); | ||||
|     connect(ui->unban, &QPushButton::clicked, this, [this] { | ||||
|         auto index = ui->ban_list_view->currentIndex(); | ||||
|         SendUnbanRequest(model->item(index.row(), 0)->text()); | ||||
|     }); | ||||
|     connect(ui->ban_list_view, &QTreeView::clicked, [this] { ui->unban->setEnabled(true); }); | ||||
| } | ||||
| 
 | ||||
| ModerationDialog::~ModerationDialog() { | ||||
|     if (callback_handle_status_message) { | ||||
|         if (auto room = Network::GetRoomMember().lock()) { | ||||
|             room->Unbind(callback_handle_status_message); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (callback_handle_ban_list) { | ||||
|         if (auto room = Network::GetRoomMember().lock()) { | ||||
|             room->Unbind(callback_handle_ban_list); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ModerationDialog::LoadBanList() { | ||||
|     if (auto room = Network::GetRoomMember().lock()) { | ||||
|         ui->refresh->setEnabled(false); | ||||
|         ui->refresh->setText(tr("Refreshing")); | ||||
|         ui->unban->setEnabled(false); | ||||
|         room->RequestBanList(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ModerationDialog::PopulateBanList(const Network::Room::BanList& ban_list) { | ||||
|     model->removeRows(0, model->rowCount()); | ||||
|     for (const auto& username : ban_list.first) { | ||||
|         QStandardItem* subject_item = new QStandardItem(QString::fromStdString(username)); | ||||
|         QStandardItem* type_item = new QStandardItem(tr("Forum Username")); | ||||
|         model->invisibleRootItem()->appendRow({subject_item, type_item}); | ||||
|     } | ||||
|     for (const auto& ip : ban_list.second) { | ||||
|         QStandardItem* subject_item = new QStandardItem(QString::fromStdString(ip)); | ||||
|         QStandardItem* type_item = new QStandardItem(tr("IP Address")); | ||||
|         model->invisibleRootItem()->appendRow({subject_item, type_item}); | ||||
|     } | ||||
|     for (int i = 0; i < Column::COUNT - 1; ++i) { | ||||
|         ui->ban_list_view->resizeColumnToContents(i); | ||||
|     } | ||||
|     ui->refresh->setEnabled(true); | ||||
|     ui->refresh->setText(tr("Refresh")); | ||||
|     ui->unban->setEnabled(false); | ||||
| } | ||||
| 
 | ||||
| void ModerationDialog::SendUnbanRequest(const QString& subject) { | ||||
|     if (auto room = Network::GetRoomMember().lock()) { | ||||
|         room->SendModerationRequest(Network::IdModUnban, subject.toStdString()); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void ModerationDialog::OnStatusMessageReceived(const Network::StatusMessageEntry& status_message) { | ||||
|     if (status_message.type != Network::IdMemberBanned && | ||||
|         status_message.type != Network::IdAddressUnbanned) | ||||
|         return; | ||||
| 
 | ||||
|     // Update the ban list for ban/unban
 | ||||
|     LoadBanList(); | ||||
| } | ||||
							
								
								
									
										42
									
								
								src/citra_qt/multiplayer/moderation_dialog.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/citra_qt/multiplayer/moderation_dialog.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | |||
| // Copyright 2018 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <optional> | ||||
| #include <QDialog> | ||||
| #include "network/room.h" | ||||
| #include "network/room_member.h" | ||||
| 
 | ||||
| namespace Ui { | ||||
| class ModerationDialog; | ||||
| } | ||||
| 
 | ||||
| class QStandardItemModel; | ||||
| 
 | ||||
| class ModerationDialog : public QDialog { | ||||
|     Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
|     explicit ModerationDialog(QWidget* parent = nullptr); | ||||
|     ~ModerationDialog(); | ||||
| 
 | ||||
| signals: | ||||
|     void StatusMessageReceived(const Network::StatusMessageEntry&); | ||||
|     void BanListReceived(const Network::Room::BanList&); | ||||
| 
 | ||||
| private: | ||||
|     void LoadBanList(); | ||||
|     void PopulateBanList(const Network::Room::BanList& ban_list); | ||||
|     void SendUnbanRequest(const QString& subject); | ||||
|     void OnStatusMessageReceived(const Network::StatusMessageEntry& status_message); | ||||
| 
 | ||||
|     std::unique_ptr<Ui::ModerationDialog> ui; | ||||
|     QStandardItemModel* model; | ||||
|     Network::RoomMember::CallbackHandle<Network::StatusMessageEntry> callback_handle_status_message; | ||||
|     Network::RoomMember::CallbackHandle<Network::Room::BanList> callback_handle_ban_list; | ||||
| }; | ||||
| 
 | ||||
| Q_DECLARE_METATYPE(Network::Room::BanList); | ||||
							
								
								
									
										84
									
								
								src/citra_qt/multiplayer/moderation_dialog.ui
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/citra_qt/multiplayer/moderation_dialog.ui
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,84 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <ui version="4.0"> | ||||
|  <class>ModerationDialog</class> | ||||
|  <widget class="QDialog" name="ModerationDialog"> | ||||
|   <property name="windowTitle"> | ||||
|    <string>Moderation</string> | ||||
|   </property> | ||||
|   <property name="geometry"> | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>500</width> | ||||
|     <height>300</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <layout class="QVBoxLayout"> | ||||
|    <item> | ||||
|     <widget class="QGroupBox" name="ban_list_group_box"> | ||||
|      <property name="title"> | ||||
|       <string>Ban List</string> | ||||
|      </property> | ||||
|      <layout class="QVBoxLayout"> | ||||
|       <item> | ||||
|        <layout class="QHBoxLayout"> | ||||
|         <item> | ||||
|          <spacer name="horizontalSpacer"> | ||||
|           <property name="orientation"> | ||||
|            <enum>Qt::Horizontal</enum> | ||||
|           </property> | ||||
|           <property name="sizeHint" stdset="0"> | ||||
|            <size> | ||||
|             <width>40</width> | ||||
|             <height>20</height> | ||||
|            </size> | ||||
|           </property> | ||||
|          </spacer> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QPushButton" name="refresh"> | ||||
|           <property name="text"> | ||||
|            <string>Refreshing</string> | ||||
|           </property> | ||||
|           <property name="enabled"> | ||||
|            <bool>false</bool> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|         <item> | ||||
|          <widget class="QPushButton" name="unban"> | ||||
|           <property name="text"> | ||||
|            <string>Unban</string> | ||||
|           </property> | ||||
|           <property name="enabled"> | ||||
|            <bool>false</bool> | ||||
|           </property> | ||||
|          </widget> | ||||
|         </item> | ||||
|        </layout> | ||||
|       </item> | ||||
|       <item> | ||||
|        <widget class="QTreeView" name="ban_list_view"/> | ||||
|       </item> | ||||
|      </layout> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item> | ||||
|     <widget class="QDialogButtonBox" name="buttonBox"> | ||||
|      <property name="standardButtons"> | ||||
|       <set>QDialogButtonBox::Ok</set> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|  <connections> | ||||
|   <connection> | ||||
|    <sender>buttonBox</sender> | ||||
|    <signal>accepted()</signal> | ||||
|    <receiver>ModerationDialog</receiver> | ||||
|    <slot>accept()</slot> | ||||
|   </connection> | ||||
|  </connections> | ||||
|  <resources/> | ||||
| </ui> | ||||
|  | @ -226,6 +226,12 @@ void MultiplayerState::OnOpenNetworkRoom() { | |||
|             if (client_room == nullptr) { | ||||
|                 client_room = new ClientRoomWindow(this); | ||||
|             } | ||||
|             const std::string host_username = member->GetRoomInformation().host_username; | ||||
|             if (host_username.empty()) { | ||||
|                 client_room->SetModPerms(false); | ||||
|             } else { | ||||
|                 client_room->SetModPerms(member->GetUsername() == host_username); | ||||
|             } | ||||
|             BringWidgetToFront(client_room); | ||||
|             return; | ||||
|         } | ||||
|  |  | |||
|  | @ -66,6 +66,7 @@ private: | |||
|     QAction* show_room; | ||||
|     std::shared_ptr<Core::AnnounceMultiplayerSession> announce_multiplayer_session; | ||||
|     Network::RoomMember::State current_state = Network::RoomMember::State::Uninitialized; | ||||
|     bool has_mod_perms = false; | ||||
|     Network::RoomMember::CallbackHandle<Network::RoomMember::State> state_callback_handle; | ||||
|     Network::RoomMember::CallbackHandle<Network::RoomMember::Error> error_callback_handle; | ||||
| }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue