citra_qt: Add a moderation dialog

The dialog currently supports accessing the ban list and removing entries from it.
This commit is contained in:
zhupengfei 2018-11-24 16:22:14 +08:00
parent 7acd2664dd
commit 6359b6094c
No known key found for this signature in database
GPG Key ID: DD129E108BD09378
9 changed files with 273 additions and 0 deletions

View File

@ -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

View File

@ -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();

View File

@ -18,6 +18,7 @@ public:
~ClientRoomWindow();
void RetranslateUi();
void SetModPerms(bool is_mod);
public slots:
void OnRoomUpdate(const Network::RoomInformation&);

View File

@ -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">

View 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();
}

View 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);

View 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>

View File

@ -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;
}

View File

@ -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;
};