Merge branch 'master' into tooomm-qt5

This commit is contained in:
tooomm 2026-09-12 18:34:48 +02:00 committed by GitHub
commit 6d7dadf657
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
149 changed files with 2962 additions and 423 deletions

View file

@ -15,6 +15,7 @@
#include "tab_card_art_rules.h"
#include "tab_deck_editor.h"
#include "tab_deck_storage.h"
#include "tab_developer.h"
#include "tab_game.h"
#include "tab_home.h"
#include "tab_logs.h"
@ -119,7 +120,7 @@ TabSupervisor::TabSupervisor(AbstractClient *_client, QMenu *tabsMenu, QWidget *
: QTabWidget(parent), userInfo(nullptr), client(_client), tabsMenu(tabsMenu), tabHome(nullptr),
tabVisualDeckStorage(nullptr), tabServer(nullptr), tabAccount(nullptr), tabDeckStorage(nullptr),
tabReplays(nullptr), tabAdmin(nullptr), tabCardArtRules(nullptr), tabLog(nullptr), tabReport(nullptr),
tabModeration(nullptr), isLocalGame(false)
tabModeration(nullptr), tabDeveloper(nullptr), isLocalGame(false)
{
setElideMode(Qt::ElideRight);
setMovable(true);
@ -205,6 +206,10 @@ TabSupervisor::TabSupervisor(AbstractClient *_client, QMenu *tabsMenu, QWidget *
aTabModeration->setCheckable(true);
connect(aTabModeration, &QAction::triggered, this, &TabSupervisor::actTabModeration);
aTabDeveloper = new QAction(this);
aTabDeveloper->setCheckable(true);
connect(aTabDeveloper, &QAction::triggered, this, &TabSupervisor::actTabDeveloper);
connect(&SettingsCache::instance().shortcuts(), &ShortcutsSettings::shortCutChanged, this,
&TabSupervisor::refreshShortcuts);
refreshShortcuts();
@ -247,6 +252,7 @@ void TabSupervisor::retranslateUi()
aTabReport->setText(tr("Report Queue"));
aTabModeration->setText(tr("Moderation"));
aTabCardArtRules->setText(tr("Card Art Rules"));
aTabDeveloper->setText(tr("Developer"));
// tabs
QList<Tab *> tabs;
@ -259,6 +265,7 @@ void TabSupervisor::retranslateUi()
tabs.append(tabReport);
tabs.append(tabModeration);
tabs.append(tabCardArtRules);
tabs.append(tabDeveloper);
QMapIterator<int, TabRoom *> roomIterator(roomTabs);
while (roomIterator.hasNext()) {
tabs.append(roomIterator.next().value());
@ -528,6 +535,19 @@ void TabSupervisor::start(const ServerInfo_User &_userInfo)
}
}
if (userInfo->user_level() & ServerInfo_User::IsDeveloper) {
tabsMenu->addSeparator();
tabsMenu->addAction(aTabDeveloper);
// Developers without moderation rights get log access through their
// own role. Moderators already have the Logs entry from above.
if (!(userInfo->user_level() & ServerInfo_User::IsModerator)) {
tabsMenu->addAction(aTabLog);
if (SettingsCache::instance().tabs().getTabLogOpen()) {
openTabLog();
}
}
}
retranslateUi();
}
@ -540,6 +560,7 @@ void TabSupervisor::startLocal(const QList<AbstractClient *> &_clients)
tabLog = nullptr;
tabReport = nullptr;
tabModeration = nullptr;
tabDeveloper = nullptr;
isLocalGame = true;
userInfo = new ServerInfo_User;
localClients = _clients;
@ -590,6 +611,9 @@ void TabSupervisor::stop()
if (tabCardArtRules) {
tabCardArtRules->close();
}
if (tabDeveloper) {
tabDeveloper->close();
}
}
QList<Tab *> tabsToDelete;
@ -819,7 +843,13 @@ void TabSupervisor::actTabLog(bool checked)
void TabSupervisor::openTabLog()
{
tabLog = new TabLog(this, client);
// Developers query logs through the developer command family, so tell the
// tab which family to use. The moderator family is strictly stronger, so a
// moderator who also holds the developer bit keeps the moderator path — the
// developer bit only selects the (narrowed) developer family on its own.
const bool useDeveloperCommands = (userInfo->user_level() & ServerInfo_User::IsDeveloper) &&
!(userInfo->user_level() & ServerInfo_User::IsModerator);
tabLog = new TabLog(this, client, useDeveloperCommands);
myAddTab(tabLog, aTabLog);
connect(tabLog, &QObject::destroyed, this, [this] {
tabLog = nullptr;
@ -881,6 +911,27 @@ void TabSupervisor::openTabModeration(const QString &userName)
aTabModeration->setChecked(true);
}
void TabSupervisor::actTabDeveloper(bool checked)
{
if (checked && !tabDeveloper) {
openTabDeveloper();
setCurrentWidget(tabDeveloper);
} else if (!checked && tabDeveloper) {
tabDeveloper->closeRequest();
}
}
void TabSupervisor::openTabDeveloper()
{
tabDeveloper = new TabDeveloper(this, client);
myAddTab(tabDeveloper, aTabDeveloper);
connect(tabDeveloper, &QObject::destroyed, this, [this] {
tabDeveloper = nullptr;
aTabDeveloper->setChecked(false);
});
aTabDeveloper->setChecked(true);
}
void TabSupervisor::updatePingTime(int value, int max)
{
if (!tabServer) {
@ -1063,6 +1114,13 @@ TabMessage *TabSupervisor::addMessageTab(const QString &receiverName, bool focus
return tab;
}
if (focus && userListManager->isUserIgnored(receiverName)) {
QMessageBox::information(
this, tr("Ignored user"),
tr("You have ignored %1. Remove them from your ignore list to open a private chat.").arg(receiverName));
return nullptr;
}
tab = new TabMessage(this, client, *userInfo, otherUser, userOnline);
connect(tab, &TabMessage::talkClosing, this, &TabSupervisor::talkLeft);
connect(tab, &TabMessage::maximizeClient, this, &TabSupervisor::maximizeMainWindow);
@ -1242,7 +1300,7 @@ void TabSupervisor::tabUserEvent(bool globalEvent)
auto *tab = static_cast<Tab *>(sender());
if (tab != currentWidget()) {
tab->setContentsChanged(true);
setTabIcon(indexOf(tab), QPixmap("theme:icons/tab_changed"));
setTabIcon(indexOf(tab), themePixmap(QStringLiteral("icons/tab_changed")));
}
if (globalEvent && SettingsCache::instance().userInterface().getNotificationsEnabled()) {
QApplication::alert(this);
@ -1277,7 +1335,21 @@ void TabSupervisor::processGameEventContainer(const GameEventContainer &cont)
void TabSupervisor::processUserMessageEvent(const Event_UserMessage &event)
{
// "Ignore all private messages" silences every PM, including messages to
// already-open tabs — unlike the unregistered/non-buddy filters below,
// which only apply when creating a new tab. Messages from moderators/admins
// are exempt to ensure warnings still reach users.
QString senderName = QString::fromStdString(event.sender_name());
if (SettingsCache::instance().chat().getIgnoreAllPrivateMessages()) {
const ServerInfo_User *onlineUserInfo = userListManager->getOnlineUser(senderName);
if (!onlineUserInfo) {
return;
}
const UserLevelFlags userLevel(onlineUserInfo->user_level());
if (!userLevel.testFlag(ServerInfo_User::IsModerator) && !userLevel.testFlag(ServerInfo_User::IsAdmin)) {
return;
}
}
TabMessage *tab = messageTabs.value(senderName);
if (!tab) {
tab = messageTabs.value(QString::fromStdString(event.receiver_name()));