diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 45428148b..fae0e6293 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -305,6 +305,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 diff --git a/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.cpp b/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.cpp index 52c9eaef0..e5b132905 100644 --- a/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.cpp +++ b/cockatrice/src/interface/widgets/dialogs/dlg_my_reports.cpp @@ -230,7 +230,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); diff --git a/cockatrice/src/interface/widgets/tabs/tab_alts.cpp b/cockatrice/src/interface/widgets/tabs/tab_alts.cpp index ca4a495b9..a88c346bf 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_alts.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_alts.cpp @@ -1,5 +1,6 @@ #include "tab_alts.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" @@ -134,7 +135,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; } @@ -390,7 +391,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); diff --git a/cockatrice/src/interface/widgets/tabs/tab_moderation.cpp b/cockatrice/src/interface/widgets/tabs/tab_moderation.cpp index 2aacfb1be..1b2ad5ad8 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_moderation.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_moderation.cpp @@ -1,5 +1,6 @@ #include "tab_moderation.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" @@ -169,7 +170,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; } @@ -449,7 +450,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) { diff --git a/cockatrice/src/interface/widgets/tabs/tab_report.cpp b/cockatrice/src/interface/widgets/tabs/tab_report.cpp index 70c4b0574..e5f1e18aa 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_report.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_report.cpp @@ -471,6 +471,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]; @@ -484,11 +487,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); } diff --git a/cockatrice/src/interface/widgets/utility/table_activation.cpp b/cockatrice/src/interface/widgets/utility/table_activation.cpp new file mode 100644 index 000000000..f6c3e4b26 --- /dev/null +++ b/cockatrice/src/interface/widgets/utility/table_activation.cpp @@ -0,0 +1,30 @@ +#include "table_activation.h" + +#include +#include +#include + +namespace +{ +void addActivationShortcut(QTableWidget *table, + QObject *context, + int key, + const std::function &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 &handler) +{ + QObject::connect(table, &QTableWidget::doubleClicked, context, handler); + addActivationShortcut(table, context, Qt::Key_Return, handler); + addActivationShortcut(table, context, Qt::Key_Enter, handler); +} diff --git a/cockatrice/src/interface/widgets/utility/table_activation.h b/cockatrice/src/interface/widgets/utility/table_activation.h new file mode 100644 index 000000000..224514d76 --- /dev/null +++ b/cockatrice/src/interface/widgets/utility/table_activation.h @@ -0,0 +1,31 @@ +/** + * @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 + +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 &handler); + +#endif // TABLE_ACTIVATION_H