Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion core/Migration.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ class Migration : public QObject
bool setSelectedProfile(const QString &tablename, const QString &profileName);
QString fixIntlField(QSqlQuery &query, const QString &columName, const QString &columnNameIntl);
bool refreshUploadStatusTrigger();

static const int latestVersion = 34;
};

Expand Down
117 changes: 116 additions & 1 deletion data/Data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Data::Data(QObject *parent) :
loadWWFF();
loadPOTA();
loadTZ();

loadUSCounties();

// dxcc_prefixes.exact DESC, dxcc_prefixes.prefix DESC
// is used because it prefers an exact-match record over a partial-match records
Expand Down Expand Up @@ -1009,6 +1009,121 @@ void Data::loadTZ()

}

void Data::loadUSCounties()
{
FCT_IDENTIFICATION;

// Database was generated from links: https://www.adif.org/316/ADIF_316.htm#Secondary_Administrative_Subdivision

if (!USCounties.isEmpty())
return; // already loaded

QFile file(":/res/data/counties.json");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qWarning() << "Failed to open counties.json";
return;
}

QByteArray jsonData = file.readAll();
file.close();

QJsonParseError parseError;
QJsonDocument doc = QJsonDocument::fromJson(jsonData, &parseError);
if (parseError.error != QJsonParseError::NoError) {
qWarning() << "JSON parse error in Counties.txt:" << parseError.errorString();
return;
}

if (!doc.isArray()) {
qWarning() << "Invalid format: root element is not an array";
return;
}

QJsonArray array = doc.array();
for (const QJsonValue &val : array) {
if (!val.isObject())
continue;

QJsonObject obj = val.toObject();
CountyInfo info;
info.DXCC = obj.value("DXCC").toInt();
info.PrimaryCode = obj.value("PrimaryCode").toString();
info.Name = obj.value("Name").toString();
info.Code = obj.value("Code").toString();
info.Aux = obj.value("Aux").toString();

if (!info.Code.isEmpty()) {
USCounties.insert(info.Code, info);
}
}

createTempUSCountyTable();

qDebug() << "Loaded" << USCounties.size() << "US counties from JSON.";
}

QString Data::lookupUSCounty(const QString &county)
{
FCT_IDENTIFICATION;

QString result;

if (USCounties.isEmpty())
loadUSCounties();

QString needle = county.trimmed();
if (needle.isEmpty())
return result;

for (const CountyInfo &info : USCounties) {
if (info.Code.compare(needle, Qt::CaseInsensitive) == 0 ||
info.Name.compare(needle, Qt::CaseInsensitive) == 0) {
return info.Code; // return first match
}
}

return result; // empty if not found
}

void Data::createTempUSCountyTable()
{
FCT_IDENTIFICATION;

QSqlQuery query;
query.exec("DROP TABLE IF EXISTS temp_uscounties");

QString createSql = R"(
CREATE TEMPORARY TABLE temp_uscounties (
DXCC INTEGER,
PrimaryCode TEXT,
Name TEXT,
Code TEXT PRIMARY KEY,
Aux TEXT
)
)";

if (!query.exec(createSql)) {
qWarning() << "Failed to create temp_uscounties:" << query.lastError().text();
return;
}

query.prepare(R"(
INSERT INTO temp_uscounties (DXCC, PrimaryCode, Name, Code, Aux)
VALUES (:dxcc, :primary, :name, :code, :aux)
)");

for (auto it = USCounties.cbegin(); it != USCounties.cend(); ++it) {
const CountyInfo &info = it.value();
query.bindValue(":dxcc", info.DXCC);
query.bindValue(":primary", info.PrimaryCode);
query.bindValue(":name", info.Name);
query.bindValue(":code", info.Code);
query.bindValue(":aux", info.Aux);
query.exec();
}
}


DxccEntity Data::lookupDxcc(const QString &callsign)
{
FCT_IDENTIFICATION;
Expand Down
28 changes: 28 additions & 0 deletions data/Data.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
#include "core/zonedetect.h"
#include "core/QuadKeyCache.h"

struct CountyInfo {
int DXCC;
QString PrimaryCode;
QString Name;
QString Code;
QString Aux;
};

class Data : public QObject
{
Q_OBJECT
Expand Down Expand Up @@ -147,6 +155,7 @@ class Data : public QObject
SOTAEntity lookupSOTA(const QString &SOTACode);
POTAEntity lookupPOTA(const QString &POTACode);
WWFFEntity lookupWWFF(const QString &reference);
QString lookupUSCounty(const QString &county);
const QString dxccFlag(int dxcc) const {return flags.value(dxcc);} ;
QPair<QString, QString> legacyMode(const QString &mode);
QStringList satModeList() { return satModes.values();}
Expand All @@ -159,6 +168,20 @@ class Data : public QObject
QStringList sotaIDList() { return sotaRefID.keys();}
QStringList wwffIDList() { return wwffRefID.keys();}
QStringList potaIDList() { return potaRefID.keys();}
QStringList uscountyList() {return USCounties.keys();}
QStringList uscountyList(int dxcc)
{
if (USCounties.isEmpty())
loadUSCounties();

QStringList list;
for (const CountyInfo &info : USCounties) {
if (info.DXCC == dxcc)
list.append(info.Code);
}
return list;
}
QHash<QString, CountyInfo> uscountyListDetailed() { return USCounties;}
QString getIANATimeZone(double, double);
QStringList sigIDList();

Expand All @@ -180,6 +203,8 @@ public slots:
void loadWWFF();
void loadPOTA();
void loadTZ();
void loadUSCounties();
void createTempUSCountyTable();

QHash<int, QString> flags;
QMap<QString, QString> contests;
Expand All @@ -190,17 +215,20 @@ public slots:
QMap<QString, QString> sotaRefID;
QMap<QString, QString> wwffRefID;
QMap<QString, QString> potaRefID;
QHash<QString, CountyInfo> USCounties;
ZoneDetect * zd;
QSqlQuery queryDXCC;
QSqlQuery queryDXCCID;
QSqlQuery querySOTA;
QSqlQuery queryWWFF;
QSqlQuery queryPOTA;
QSqlQuery queryUSCounty;
bool isDXCCQueryValid;
bool isSOTAQueryValid;
bool isWWFFQueryValid;
bool isPOTAQueryValid;
bool isDXCCIDQueryValid;

QuadKeyCache<DxccStatus> dxccStatusCache;

static const char translitTab[];
Expand Down
Loading
Loading