atrooney-online-2/src/widgets/playerlistwidget.cpp
Salanto 4db9791873
Close punishment dialog when the user leaves (#1097)
* Close punishment dialog when the user leaves

Prevents silly moments where the wrong person gets banned/kicked

* Fix formatting

---------

Co-authored-by: stonedDiscord <Tukz@gmx.de>
2025-05-08 14:21:37 -05:00

209 lines
5.5 KiB
C++

#include "playerlistwidget.h"
#include "aoapplication.h"
#include "moderation_functions.h"
#include "widgets/moderator_dialog.h"
#include <QListWidgetItem>
#include <QMenu>
PlayerListWidget::PlayerListWidget(AOApplication *ao_app, QWidget *parent)
: QListWidget(parent)
, ao_app(ao_app)
{
setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &PlayerListWidget::customContextMenuRequested, this, &PlayerListWidget::onCustomContextMenuRequested);
}
PlayerListWidget::~PlayerListWidget()
{}
void PlayerListWidget::registerPlayer(const PlayerRegister &update)
{
switch (update.type)
{
default:
Q_UNREACHABLE();
break;
case PlayerRegister::ADD_PLAYER:
addPlayer(update.id);
break;
case PlayerRegister::REMOVE_PLAYER:
removePlayer(update.id);
break;
}
}
void PlayerListWidget::updatePlayer(const PlayerUpdate &update)
{
PlayerData &player = m_player_map[update.id];
bool update_icon = false;
switch (update.type)
{
default:
Q_UNREACHABLE();
break;
case PlayerUpdate::NAME:
player.name = update.data;
break;
case PlayerUpdate::CHARACTER:
player.character = update.data;
update_icon = true;
break;
case PlayerUpdate::CHARACTER_NAME:
player.character_name = update.data;
break;
case PlayerUpdate::AREA_ID:
player.area_id = update.data.toInt();
break;
}
updatePlayer(player.id, update_icon);
filterPlayerList();
}
void PlayerListWidget::reloadPlayers()
{
for (const PlayerData &player : std::as_const(m_player_map))
{
updatePlayer(player.id, false);
}
}
void PlayerListWidget::setAuthenticated(bool f_state)
{
m_is_authenticated = f_state;
for (const PlayerData &data : std::as_const(m_player_map))
{
updatePlayer(data.id, false);
filterPlayerList();
}
}
void PlayerListWidget::onCustomContextMenuRequested(const QPoint &pos)
{
QListWidgetItem *item = itemAt(pos);
if (item == nullptr)
{
return;
}
int id = item->data(Qt::UserRole).toInt();
QString name = item->text();
QMenu *menu = new QMenu(this);
menu->setAttribute(Qt::WA_DeleteOnClose);
QAction *report_player_action = menu->addAction("Report Player");
connect(report_player_action, &QAction::triggered, this, [this, id, name] {
auto maybe_reason = call_moderator_support(name);
if (maybe_reason.has_value())
{
ao_app->send_server_packet(AOPacket("ZZ", {maybe_reason.value(), QString::number(id)}));
}
});
if (m_is_authenticated)
{
QAction *kick_player_action = menu->addAction("Kick");
connect(kick_player_action, &QAction::triggered, this, [this, id, name] {
ModeratorDialog *dialog = new ModeratorDialog(id, false, ao_app);
dialog->setWindowTitle(tr("Kick %1").arg(name));
connect(this, &PlayerListWidget::destroyed, dialog, &ModeratorDialog::deleteLater);
active_moderator_menu = {id, dialog};
dialog->show();
});
QAction *ban_player_action = menu->addAction("Ban");
connect(ban_player_action, &QAction::triggered, this, [this, id, name] {
ModeratorDialog *dialog = new ModeratorDialog(id, true, ao_app);
dialog->setWindowTitle(tr("Ban %1").arg(name));
connect(this, &PlayerListWidget::destroyed, dialog, &ModeratorDialog::deleteLater);
active_moderator_menu = {id, dialog};
dialog->show();
});
}
menu->popup(mapToGlobal(pos));
}
void PlayerListWidget::addPlayer(int playerId)
{
m_player_map.insert(playerId, PlayerData{.id = playerId});
QListWidgetItem *item = new QListWidgetItem(this);
item->setData(Qt::UserRole, playerId);
m_item_map.insert(playerId, item);
updatePlayer(playerId, false);
}
void PlayerListWidget::removePlayer(int playerId)
{
if (active_moderator_menu.first == playerId && active_moderator_menu.second)
{
delete active_moderator_menu.second;
Q_EMIT notify("Closed Moderation Dialog : User left the server.");
}
delete takeItem(row(m_item_map.take(playerId)));
m_player_map.remove(playerId);
}
void PlayerListWidget::filterPlayerList()
{
int area_id = m_player_map.value(ao_app->client_id).area_id;
for (QListWidgetItem *item : std::as_const(m_item_map))
{
if (!item)
{
qWarning() << "Trying to filter item that does not exist. This indicates either a broken server-implementation or a bad demo file.";
break;
}
item->setHidden(m_player_map[item->data(Qt::UserRole).toInt()].area_id != area_id && !m_is_authenticated);
}
}
void PlayerListWidget::updatePlayer(int playerId, bool updateIcon)
{
PlayerData &data = m_player_map[playerId];
QListWidgetItem *item = m_item_map[playerId];
if (!item)
{
qWarning() << "No player at ID" << playerId << ". This might indicate a broker server implementation or a bad demo file.";
return;
}
item->setText(formatLabel(data));
if (data.character.isEmpty())
{
item->setToolTip(QString());
return;
}
QString tooltip = data.character;
if (!data.character_name.isEmpty())
{
tooltip = QObject::tr("%1 aka %2").arg(data.character, data.character_name);
}
item->setToolTip(tooltip);
if (updateIcon)
{
item->setIcon(QIcon(ao_app->get_image_suffix(ao_app->get_character_path(data.character, "char_icon"), true)));
}
}
QString PlayerListWidget::formatLabel(const PlayerData &data)
{
QString format = Options::getInstance().playerlistFormatString();
return format.replace("{id}", QString::number(data.id)).replace("{character}", data.character).replace("{displayname}", data.character_name.isEmpty() ? "No Data" : data.character_name).replace("{username}", data.name).simplified();
}