[Client] Fix alt badge and trail review findings

- Drop the dead VPN warning branch: rowVisible() already hides IP rows
  above the threshold, so setVpnThreshold(), its member and the spin-box
  connect never took effect.
- Dim IP rows at shared_count > 2 instead of > 1: the count already
  includes the investigated account, so every IP row was dimmed.
- Truncate backStack when a breadcrumb is clicked instead of pushing the
  current user again, so the trail keeps a single path and Back works.
- Word-wrap the trail label so a long chain cannot widen the tab.
- Extract the status/match pill painting into widgets/utility/pill_painter
  and use it from both delegates instead of duplicating it.
This commit is contained in:
Lukas Brübach 2026-11-01 12:21:16 +01:00
parent 803e1e9ec3
commit 7495703c02
8 changed files with 120 additions and 92 deletions

View file

@ -107,9 +107,12 @@ TabAlts::TabAlts(TabSupervisor *_tabSupervisor, AbstractClient *_client, const Q
trailLabel->setTextFormat(Qt::RichText);
trailLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
trailLabel->setOpenExternalLinks(false);
// The trail grows with every hop, so let it wrap instead of forcing the tab
// wider than the window.
trailLabel->setWordWrap(true);
connect(trailLabel, &QLabel::linkActivated, this, [this](const QString &userName) {
if (!userName.isEmpty() && userName != currentUser) {
investigate(userName);
goToTrailEntry(userName);
}
});
@ -147,8 +150,6 @@ TabAlts::TabAlts(TabSupervisor *_tabSupervisor, AbstractClient *_client, const Q
altsTable = new QTableWidget(0, COL_ALTS_COUNT);
configureAltTable(altsTable);
altsDelegate = new AltTableDelegate(COL_ALTS_VIA, COL_ALTS_WARNS, COL_ALTS_BANS, COL_ALTS_SHARED, altsTable);
altsDelegate->setVpnThreshold(vpnSpin->value());
connect(vpnSpin, &QSpinBox::valueChanged, altsDelegate, &AltTableDelegate::setVpnThreshold);
altsTable->setItemDelegateForColumn(COL_ALTS_VIA, altsDelegate);
altsTable->setItemDelegateForColumn(COL_ALTS_WARNS, altsDelegate);
altsTable->setItemDelegateForColumn(COL_ALTS_BANS, altsDelegate);
@ -271,6 +272,20 @@ void TabAlts::investigate(const QString &userName)
loadUser(userName);
}
void TabAlts::goToTrailEntry(const QString &userName)
{
const int index = backStack.indexOf(userName);
if (index < 0) {
investigate(userName);
return;
}
// Clicking an earlier crumb truncates the history there instead of pushing
// another entry, so the trail keeps a single path and Back still works.
backStack.erase(backStack.begin() + index, backStack.end());
backButton->setEnabled(!backStack.isEmpty());
loadUser(userName);
}
void TabAlts::goBack()
{
if (backStack.isEmpty()) {
@ -441,6 +456,8 @@ void TabAlts::renderTable()
altsTable->setItem(row, COL_ALTS_WARNS, new QTableWidgetItem(QString::number(alt.warn_count())));
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")));
// shared_count already includes the investigated account, so anything
// above 2 means the address is shared beyond that pair.
if (QString::fromStdString(alt.match_reason()).startsWith(QStringLiteral("ip:")) && alt.has_shared_count() &&
alt.shared_count() > 2) {
for (int col = 0; col < COL_ALTS_COUNT; ++col) {