Skip to content

Commit 0f93eda

Browse files
authored
wsjtx: fix 'calling me' spot never firing (#5823)
DxClusterCallsign was the only source for myCall; operators without a DX cluster login configured got an empty string, so isCallingMe was always false and red spots never appeared on the pan. Fall back to m_radioModel.callsign() when DxClusterCallsign is empty. Also made the comparison case-insensitive and strip angle-bracket hash notation and /P suffixes before comparing so portable/hashed calls match. Candidate 2 of #5823; does not close the issue. Squashed-from: #5841 Co-authored-by: rah501xx <279323019+WA8PAM@users.noreply.github.com>
1 parent 8d8add8 commit 0f93eda

2 files changed

Lines changed: 50 additions & 4 deletions

File tree

src/gui/DxClusterDialog.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,20 @@ QColor getColorForLiveParent(const QColor& initial, DxClusterDialog* parent,
5858
return parentGuard ? color : QColor();
5959
}
6060

61+
// Normalizes a callsign before a "calling me?" comparison — same logic as
62+
// MainWindow_Spots.cpp. Applied to both the message token and the configured
63+
// callsign so /P-style suffixes and <hash> calls match on both sides (#5823).
64+
QString normalizeCallForMatch(QString c)
65+
{
66+
c = c.trimmed();
67+
if (c.size() > 2 && c.startsWith(QLatin1Char('<')) && c.endsWith(QLatin1Char('>')))
68+
c = c.mid(1, c.size() - 2);
69+
const int slash = c.indexOf(QLatin1Char('/'));
70+
if (slash > 0)
71+
c = c.left(slash);
72+
return c;
73+
}
74+
6175
} // namespace
6276

6377
// GuardedSlider variant that resets to a stored default on left
@@ -509,10 +523,13 @@ DxClusterDialog::DxClusterDialog(DxClusterClient* clusterClient, DxClusterClient
509523
bool isPOTA = msg.contains("CQ POTA");
510524
bool isCallingMe = false;
511525
{
512-
QString myCall = as.value("DxClusterCallsign").toString();
526+
// Same fallback and normalization as MainWindow_Spots.cpp (#5823).
527+
QString myCall = normalizeCallForMatch(
528+
as.value("DxClusterCallsign").toString());
513529
if (!myCall.isEmpty()) {
514530
QStringList parts = msg.split(' ', Qt::SkipEmptyParts);
515-
if (parts.size() >= 2 && parts[0] == myCall)
531+
if (parts.size() >= 2 &&
532+
normalizeCallForMatch(parts[0]).compare(myCall, Qt::CaseInsensitive) == 0)
516533
isCallingMe = true;
517534
}
518535
}

src/gui/MainWindow_Spots.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,24 @@
4747
#include <cmath>
4848
#include <memory>
4949

50+
namespace {
51+
// Normalizes a callsign before a "calling me?" comparison. Applied to BOTH
52+
// the message token and the configured/radio callsign so portable suffixes
53+
// (/P, /QRP, /M …) and angle-bracket hashed calls (<K1ABC>) match correctly
54+
// on both sides. Without this, a configured callsign like VE3ABC/P would stop
55+
// matching after stripping only the message side (#5823 review blocker).
56+
QString normalizeCallForMatch(QString c)
57+
{
58+
c = c.trimmed();
59+
if (c.size() > 2 && c.startsWith(QLatin1Char('<')) && c.endsWith(QLatin1Char('>')))
60+
c = c.mid(1, c.size() - 2);
61+
const int slash = c.indexOf(QLatin1Char('/'));
62+
if (slash > 0)
63+
c = c.left(slash);
64+
return c;
65+
}
66+
} // namespace
67+
5068
namespace AetherSDR {
5169

5270
void MainWindow::wireSpotSubsystem()
@@ -695,10 +713,21 @@ void MainWindow::wireSpotSubsystem()
695713
bool isPOTA = msg.contains("CQ POTA");
696714
bool isCallingMe = false;
697715
{
698-
QString myCall = as.value("DxClusterCallsign").toString();
716+
// Prefer the explicit cluster login callsign; fall back to the
717+
// radio's own callsign so operators who never configure a DX
718+
// cluster login still get "calling me" spots (#5823).
719+
// RadioModel::callsign() already trims, so no .trimmed() needed.
720+
QString myCall = as.value("DxClusterCallsign").toString().trimmed();
721+
if (myCall.isEmpty())
722+
myCall = m_radioModel.callsign();
723+
// Normalize BOTH sides through the same helper before comparing so
724+
// a configured call like VE3ABC/P matches the stripped message token
725+
// VE3ABC, and a hashed <K1ABC> in the decode matches K1ABC on file.
726+
myCall = normalizeCallForMatch(myCall);
699727
if (!myCall.isEmpty()) {
700728
QStringList parts = msg.split(' ', Qt::SkipEmptyParts);
701-
if (parts.size() >= 2 && parts[0] == myCall)
729+
if (parts.size() >= 2 &&
730+
normalizeCallForMatch(parts[0]).compare(myCall, Qt::CaseInsensitive) == 0)
702731
isCallingMe = true;
703732
}
704733
}

0 commit comments

Comments
 (0)