Fix remaining review threads on the report queue dashboard

- Read the raw report status from Qt::UserRole in DlgMyReports, so regular
  users can comment on their own open reports again.
- Exclude the server's depth-0 seed row from the related-alt count.
- Dim only IP matches shared by more than the pair, not every IP match.
- Activate alts rows on double-click or Enter instead of `activated`, which
  fires on a single click on single-click platforms.
- Fold the reported-user bolding pass into the fill loop.
This commit is contained in:
Lukas Brübach 2026-11-01 05:29:12 +01:00
parent 31878eb880
commit 4d645e7513
8 changed files with 81 additions and 10 deletions

View file

@ -289,6 +289,8 @@ set(cockatrice_SOURCES
src/interface/widgets/utility/get_text_with_max.cpp
src/interface/widgets/utility/report_utils.cpp
src/interface/widgets/utility/report_utils.h
src/interface/widgets/utility/table_activation.cpp
src/interface/widgets/utility/table_activation.h
src/interface/widgets/utility/sequence_edit.cpp
src/interface/widgets/utility/visibility_change_listener.cpp
src/interface/widgets/utility/visibility_change_listener.h

View file

@ -223,7 +223,8 @@ void DlgMyReports::onSelectionChanged()
connect(pend, &PendingCommand::finished, this, &DlgMyReports::reportDetailsResponse);
client->sendCommand(pend);
QString status = table->item(row, COL_STATUS)->text();
// The cell text is the translated label; the raw status lives in UserRole.
const QString status = table->item(row, COL_STATUS)->data(Qt::UserRole).toString();
bool canComment = (status == "open" || status == "assigned");
commentButton->setEnabled(canComment);
commentInput->setEnabled(canComment);

View file

@ -1,6 +1,7 @@
#include "tab_alts.h"
#include "../utility/epoch_format.h"
#include "../utility/table_activation.h"
#include "abstract_client.h"
#include "libcockatrice/protocol/pb/response.pb.h"
#include "libcockatrice/protocol/pb/response_user_alts.pb.h"
@ -135,7 +136,7 @@ TabAlts::TabAlts(TabSupervisor *_tabSupervisor, AbstractClient *_client, const Q
altsTable = new QTableWidget(0, COL_ALTS_COUNT);
configureAltTable(altsTable);
connect(altsTable, &QTableWidget::activated, this, [this](const QModelIndex &index) {
connectTableActivation(altsTable, this, [this](const QModelIndex &index) {
if (!index.isValid()) {
return;
}
@ -393,7 +394,7 @@ void TabAlts::renderTable()
altsTable->setItem(row, COL_ALTS_BANS, new QTableWidgetItem(QString::number(alt.ban_count())));
altsTable->setItem(row, COL_ALTS_ACTIVE, new QTableWidgetItem(alt.is_active() ? tr("yes") : tr("no")));
if (QString::fromStdString(alt.match_reason()).startsWith(QStringLiteral("ip:")) && alt.has_shared_count() &&
alt.shared_count() > 1) {
alt.shared_count() > 2) {
for (int col = 0; col < COL_ALTS_COUNT; ++col) {
if (auto *item = altsTable->item(row, col)) {
item->setForeground(dimColor);

View file

@ -1,6 +1,7 @@
#include "tab_moderation.h"
#include "../utility/epoch_format.h"
#include "../utility/table_activation.h"
#include "abstract_client.h"
#include "libcockatrice/protocol/pb/admin_commands.pb.h"
#include "libcockatrice/protocol/pb/response.pb.h"
@ -176,7 +177,7 @@ TabModeration::TabModeration(TabSupervisor *_tabSupervisor, AbstractClient *_cli
altsTable = new QTableWidget(0, COL_ALTS_COUNT);
configureTable(altsTable);
connect(altsTable, &QTableWidget::activated, this, [this](const QModelIndex &index) {
connectTableActivation(altsTable, this, [this](const QModelIndex &index) {
if (!index.isValid()) {
return;
}
@ -456,7 +457,14 @@ void TabModeration::altsResponse(const Response &response)
}
const Response_UserAlts &resp = response.GetExtension(Response_UserAlts::ext);
cachedAltsCount = resp.alts_size();
// The server always includes the frontier user as a depth-0 seed row.
int relatedCount = 0;
for (int i = 0; i < resp.alts_size(); ++i) {
if (!resp.alts(i).has_depth() || resp.alts(i).depth() > 0) {
++relatedCount;
}
}
cachedAltsCount = relatedCount;
applyAltsCount();
altsTable->setRowCount(resp.alts_size());
for (int i = 0; i < resp.alts_size(); ++i) {

View file

@ -463,6 +463,9 @@ void TabReport::applyFilters()
table->setSortingEnabled(false);
table->setRowCount(filteredReports.size());
QFont reportedFont = table->font();
reportedFont.setBold(true);
for (int row = 0; row < filteredReports.size(); ++row) {
const ServerInfo_Report &r = filteredReports[row];
@ -476,11 +479,7 @@ void TabReport::applyFilters()
table->setItem(row, COL_ROOM,
new QTableWidgetItem(r.has_room_id() && r.room_id() > 0 ? QString::number(r.room_id()) : ""));
}
QFont reportedFont = table->font();
reportedFont.setBold(true);
for (int row = 0; row < filteredReports.size(); ++row) {
if (auto *reportedItem = table->item(row, COL_REPORTED)) {
reportedItem->setFont(reportedFont);
}

View file

@ -0,0 +1,28 @@
#include "table_activation.h"
#include <QKeySequence>
#include <QShortcut>
#include <QTableWidget>
namespace
{
void addActivationShortcut(QTableWidget *table,
QObject *context,
int key,
const std::function<void(const QModelIndex &)> &handler)
{
auto *shortcut = new QShortcut(QKeySequence(key), table);
// The table's viewport takes focus, so match children as well.
shortcut->setContext(Qt::WidgetWithChildrenShortcut);
QObject::connect(shortcut, &QShortcut::activated, context, [table, handler] { handler(table->currentIndex()); });
}
} // namespace
void connectTableActivation(QTableWidget *table,
QObject *context,
const std::function<void(const QModelIndex &)> &handler)
{
QObject::connect(table, &QTableWidget::doubleClicked, context, handler);
addActivationShortcut(table, context, Qt::Key_Return, handler);
addActivationShortcut(table, context, Qt::Key_Enter, handler);
}

View file

@ -0,0 +1,32 @@
/**
* @file table_activation.h
* @brief Row activation for tables that must not navigate on a single click.
*/
#ifndef TABLE_ACTIVATION_H
#define TABLE_ACTIVATION_H
#include <functional>
class QModelIndex;
class QObject;
class QTableWidget;
/**
* @brief Call @p handler on double-click or Enter, never on a single click.
*
* QAbstractItemView::activated fires on a single click on platforms where
* SH_ItemView_ActivateItemOnSingleClick is set, so navigation actions must not
* use it. This connects doubleClicked and installs Return/Enter shortcuts that
* forward the current index.
*
* @param table The table whose rows activate.
* @param context Object that owns the connections; the handler is disconnected
* with it.
* @param handler Receives the activated row's index, which may be invalid.
*/
void connectTableActivation(QTableWidget *table,
QObject *context,
const std::function<void(const QModelIndex &)> &handler);
#endif // TABLE_ACTIVATION_H

2
vcpkg

@ -1 +1 @@
Subproject commit 9eec002df1cd109f8f104cd966a763daf9751489
Subproject commit 9e593bb18ea69cc5095e012465dcd675a822ed0d