Background
This is a continuation of the 6-phase Exchange Enhancement plan (wild-scribbling-shore.md). Phases 1-3 have been completed in v3.31.0+:
✅ Completed (Phases 1-3)
- Phase 1: Validation and parsing connected to logging flow (v3.31.0)
- Exchange validation called before database save
parsedExchange field populated
- RST auto-detection and auto-prepending
- Phase 2: Auto-population infrastructure (v3.31.0+)
- Basic exchange auto-population from contest rules
- Context-aware field enabling in Edit QSO Dialog
- Phase 3: Database schema for exchange fields (v3.31.1+)
- Exchange field columns added to database schema
- Exchange received formatting across all contests
⚠️ Remaining Work (Phases 4-6)
The following phases need implementation to achieve TR4W-level exchange sophistication:
Phase 4: Smart Navigation & Field Management
Goal: TR4W-style keyboard workflow - minimal mouse, auto-focus, smart spacing
Features to Implement
1. Auto-Focus Logic
- Auto-focus to exchange field after 3+ chars in callsign (configurable threshold)
- Located in
MainWindow::onCallsignChanged() (~line 1377)
void MainWindow::onCallsignChanged(const QString& callsign) {
autoPopulateExchange(callsign);
// NEW: Auto-focus to exchange after threshold
AppSettings& settings = AppSettings::instance();
int threshold = settings.getAutoFocusThreshold(); // Default: 3
if (callsign.length() >= threshold && m_exchangeEntry->text().isEmpty()) {
m_exchangeEntry->setFocus();
}
}
2. Exchange Overwrite Mode
- When exchange is auto-populated, select all text so first keystroke replaces
- Reduces keystrokes when auto-fill is wrong
// In autoPopulateExchange() after setting text
if (!prediction.isEmpty()) {
m_exchangeEntry->setText(prediction);
m_exchangeEntry->selectAll(); // Next keystroke replaces entire field
}
3. Smart Space Insertion (Optional)
- Auto-insert space between fields (e.g., "5991" → "599 1" for CQWW)
- New class:
SmartExchangeParser::autoSpace()
4. Tab Completion for Sections
- QCompleter for section autocomplete (e.g., "WM" + Tab → "WMA")
5. Settings Integration
- Add to
AppSettings.h/cpp:
setAutoFocusThreshold(int chars) - Default: 3
setAutoSpaceEnabled(bool) - Default: false
setExchangeOverwriteMode(bool) - Default: true
Testing Checklist
Deliverable: Hands stay on keyboard; <20 keystrokes per QSO (down from ~30)
Phase 5: Exchange Memory Database & Persistence
Goal: Exchange memory persists across sessions and improves over time
Features to Implement
1. Database Persistence Verification
- Ensure
exchange_memory table survives app restarts
- Test schema loading in
Database::loadSchemaSql()
- Add migration for existing databases
2. Memory Manager UI (New Dialog)
New files:
/src/ui/dialogs/ExchangeMemoryDialog.h
/src/ui/dialogs/ExchangeMemoryDialog.cpp
class ExchangeMemoryDialog : public QDialog {
Q_OBJECT
public:
explicit ExchangeMemoryDialog(QWidget* parent = nullptr);
private:
QTableView* m_memoryTable;
ExchangeMemoryTableModel* m_model;
QPushButton* m_deleteButton;
QPushButton* m_importButton;
QPushButton* m_exportButton;
QPushButton* m_clearOldButton;
QLabel* m_statsLabel; // Shows: "782 entries, 63% hit rate"
};
Menu Integration: Tools → Exchange Memory Manager
3. Export to CSV
For backup and sharing:
callsign,exchange,contest_type,mode,timestamp,hit_count
W1AW,1O MA,WFD,CW,1703462400,5
K6XX,599 3,CQWW,CW,1703548800,2
4. Statistics & Metrics
Track memory performance:
- Hit rate: successful lookups / total lookups
- Coverage: unique callsigns in memory
- Freshness: average age of entries
- Top sources: most frequently looked up
Display in ExchangeMemoryDialog status bar
5. Import from TR4W TRMASTER.DTA (Stretch Goal)
- Convert TR4W's binary master database to TR4QT exchange_memory
- TR4W format: Binary file with callsign records (Name, QTH, Section, Zone, Check)
Testing Checklist
Deliverable: Exchange memory persists and improves; >80% hit rate after 500 QSOs
Phase 6: Advanced Features & DOM Files
Goal: Contest-specific resources, smart parsing, TR4W-level sophistication
Features to Implement
1. JSON Resource Files for Contest Data
Replace hardcoded sections/zones with JSON resources:
New files:
/resources/contests/WFD_sections.json
/resources/contests/ARRL_sections.json
/resources/contests/RAC_sections.json
/resources/contests/CQ_zones.json
Example (WFD_sections.json):
{
"contest": "WFD",
"version": "2024",
"sections": {
"US": [
{"code": "CT", "name": "Connecticut", "aliases": ["CONN"]},
{"code": "WMA", "name": "Western Massachusetts"},
{"code": "EMA", "name": "Eastern Massachusetts"}
],
"Canada": [
{"code": "MAR", "name": "Maritime"},
{"code": "QC", "name": "Quebec"}
],
"Other": [
{"code": "DX", "name": "DX (non-US/VE)"}
]
},
"classes": ["1O", "1I", "2O", "2I", "3O", "HOME"]
}
2. Contest Resource Loader
New files:
/src/contests/ContestResourceLoader.h
/src/contests/ContestResourceLoader.cpp
class ContestResourceLoader {
public:
static QStringList loadValidSections(const QString& contestId);
static QStringList loadValidClasses(const QString& contestId);
static QMap<QString, QString> loadSectionAliases(const QString& contestId);
private:
static QJsonDocument loadResource(const QString& contestId, const QString& resourceType);
static QCache<QString, QJsonDocument> s_cache;
};
3. Update Contests to Use Resources
Modify: /src/contests/WinterFieldDayContest.cpp (lines 226-251)
Replace hardcoded sections with:
bool WinterFieldDayContest::isValidSection(const QString& section) const {
static QStringList validSections = ContestResourceLoader::loadValidSections("WFD");
return validSections.contains(section.toUpper());
}
4. Smart Multi-Field Parser
New files:
/src/exchanges/SmartExchangeParser.h
/src/exchanges/SmartExchangeParser.cpp
TR4W's ParseArray() equivalent - detect field types and reorder:
class SmartExchangeParser {
public:
enum class FieldType { Numeric, Alpha, Mixed, RST };
struct ParsedField {
FieldType type;
QString value;
int position;
};
// Analyze field types
static QList<ParsedField> analyzeFields(const QString& exchange);
// Reorder to match expected format
// E.g., "WTX 2A" → "2A WTX" for WFD
static QString normalizeOrder(const QString& exchange,
const QList<ExchangeField>& expectedFields);
};
5. Context-Sensitive Help (F1 Key)
Add F1 key handler to exchange field:
bool MainWindow::eventFilter(QObject* obj, QEvent* event) {
if (obj == m_exchangeEntry && event->type() == QEvent::KeyPress) {
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_F1) {
showExchangeHelp();
return true;
}
}
return QMainWindow::eventFilter(obj, event);
}
void MainWindow::showExchangeHelp() {
if (!m_activeContest) return;
QString help = "Exchange format: ";
QList<ExchangeField> fields = m_activeContest->getReceivedExchangeFields();
for (const ExchangeField& field : fields) {
help += field.hint + " ";
}
// Show valid values for current contest
if (m_activeContest->getContestId() == "WFD") {
QStringList sections = ContestResourceLoader::loadValidSections("WFD");
help += "\n\nValid sections: " + sections.join(", ");
}
DialogHelper::information(this, "Exchange Help", help);
}
6. Exchange Statistics
Add Tools menu item: "Exchange Statistics"
Show:
- Zone/section distribution (bar chart using QCustomPlot)
- Most common exchanges
- Unusual exchanges (outliers)
- Missing multipliers
Testing Checklist
Deliverable: TR4W-equivalent sophistication; forgiving parser; comprehensive validation
Files to Create
Phase 4
- None (modifications only)
Phase 5
/src/ui/dialogs/ExchangeMemoryDialog.h
/src/ui/dialogs/ExchangeMemoryDialog.cpp
Phase 6
/src/contests/ContestResourceLoader.h
/src/contests/ContestResourceLoader.cpp
/src/exchanges/SmartExchangeParser.h
/src/exchanges/SmartExchangeParser.cpp
/resources/contests/WFD_sections.json
/resources/contests/ARRL_sections.json
/resources/contests/RAC_sections.json
/resources/contests/CQ_zones.json
Files to Modify
Phase 4
/src/ui/MainWindow.cpp
- Line 1377: Add auto-focus logic in
onCallsignChanged()
- Lines 1741-1771: Add overwrite mode to
autoPopulateExchange()
/src/ui/MainWindow.h
- Add event filter declaration
/src/utils/AppSettings.h
- Add:
getAutoFocusThreshold(), getAutoSpaceEnabled(), getExchangeOverwriteMode()
/src/utils/AppSettings.cpp
- Implement settings persistence
Phase 5
/src/CMakeLists.txt
- Add ExchangeMemoryDialog to build
/src/ui/MainWindow.cpp
- Add Tools menu item for Exchange Memory Manager
Phase 6
/src/contests/WinterFieldDayContest.cpp
- Lines 226-251: Replace hardcoded sections with JSON loader
/src/CMakeLists.txt
- Add Qt resource file for JSON resources
- Add SmartExchangeParser and ContestResourceLoader to build
/src/ui/MainWindow.cpp
- Add F1 event filter for exchange help
- Add Tools menu item for Exchange Statistics
Success Metrics
Phase 4
- Goal: Reduced keystrokes per QSO
- Metric: <20 keystrokes per QSO (down from ~30)
- Measurement: Log 50 QSOs and count keystrokes
Phase 5
- Goal: Persistent exchange knowledge
- Metric: Memory DB size grows linearly with unique calls
- Measurement: >80% hit rate after 500 QSOs
Phase 6
- Goal: TR4W-level sophistication
- Metric: Log 100 WFD QSOs with <5% manual corrections
- Measurement: Parser accepts "WTX 2A" and reorders automatically
References
Original Plan: ~/.claude/plans/wild-scribbling-shore.md
Completed Work:
- v3.31.0: Complete exchange received formatting across all contests
- v3.31.1: Fix database schema bug - Add missing exchange field columns
- v3.31.3: Context-aware field enabling in Edit QSO Dialog
- v3.31.5: Add Operator Name field to Edit QSO Dialog
- v3.31.6: Document exchange field database schema architecture
TR4W Reference (for feature parity):
/Users/toms/projects/TR4W/tr4w/src/trdos/LOGEDIT.PAS (line 2207 - InitialExchangeEntry)
/Users/toms/projects/TR4W/tr4w/src/trdos/LOGSTUFF.PAS (line 8516 - ProcessExchange)
/Users/toms/projects/TR4W/tr4w/src/MainUnit.pas (exchange UI handling)
TR4QT Codebase:
/src/ui/MainWindow.cpp (lines 1258-1372, 1710-1771)
/src/contests/ContestBase.h (exchange API)
/src/contests/WinterFieldDayContest.cpp (complex validation example)
Implementation Strategy
Recommended order:
- Phase 4 (1-2 weeks) - Immediate UX improvement, low risk
- Phase 6 (2-3 weeks) - Foundation for Phase 5 (resource loader needed)
- Phase 5 (1-2 weeks) - UI polish, depends on Phase 6 resources
Total: 4-7 weeks for complete TR4W-equivalent exchange system
Milestones:
Background
This is a continuation of the 6-phase Exchange Enhancement plan (wild-scribbling-shore.md). Phases 1-3 have been completed in v3.31.0+:
✅ Completed (Phases 1-3)
parsedExchangefield populatedThe following phases need implementation to achieve TR4W-level exchange sophistication:
Phase 4: Smart Navigation & Field Management
Goal: TR4W-style keyboard workflow - minimal mouse, auto-focus, smart spacing
Features to Implement
1. Auto-Focus Logic
MainWindow::onCallsignChanged()(~line 1377)2. Exchange Overwrite Mode
3. Smart Space Insertion (Optional)
SmartExchangeParser::autoSpace()4. Tab Completion for Sections
5. Settings Integration
AppSettings.h/cpp:setAutoFocusThreshold(int chars)- Default: 3setAutoSpaceEnabled(bool)- Default: falsesetExchangeOverwriteMode(bool)- Default: trueTesting Checklist
Deliverable: Hands stay on keyboard; <20 keystrokes per QSO (down from ~30)
Phase 5: Exchange Memory Database & Persistence
Goal: Exchange memory persists across sessions and improves over time
Features to Implement
1. Database Persistence Verification
exchange_memorytable survives app restartsDatabase::loadSchemaSql()2. Memory Manager UI (New Dialog)
New files:
/src/ui/dialogs/ExchangeMemoryDialog.h/src/ui/dialogs/ExchangeMemoryDialog.cppMenu Integration: Tools → Exchange Memory Manager
3. Export to CSV
For backup and sharing:
4. Statistics & Metrics
Track memory performance:
Display in ExchangeMemoryDialog status bar
5. Import from TR4W TRMASTER.DTA (Stretch Goal)
Testing Checklist
Deliverable: Exchange memory persists and improves; >80% hit rate after 500 QSOs
Phase 6: Advanced Features & DOM Files
Goal: Contest-specific resources, smart parsing, TR4W-level sophistication
Features to Implement
1. JSON Resource Files for Contest Data
Replace hardcoded sections/zones with JSON resources:
New files:
/resources/contests/WFD_sections.json/resources/contests/ARRL_sections.json/resources/contests/RAC_sections.json/resources/contests/CQ_zones.jsonExample (
WFD_sections.json):{ "contest": "WFD", "version": "2024", "sections": { "US": [ {"code": "CT", "name": "Connecticut", "aliases": ["CONN"]}, {"code": "WMA", "name": "Western Massachusetts"}, {"code": "EMA", "name": "Eastern Massachusetts"} ], "Canada": [ {"code": "MAR", "name": "Maritime"}, {"code": "QC", "name": "Quebec"} ], "Other": [ {"code": "DX", "name": "DX (non-US/VE)"} ] }, "classes": ["1O", "1I", "2O", "2I", "3O", "HOME"] }2. Contest Resource Loader
New files:
/src/contests/ContestResourceLoader.h/src/contests/ContestResourceLoader.cpp3. Update Contests to Use Resources
Modify:
/src/contests/WinterFieldDayContest.cpp(lines 226-251)Replace hardcoded sections with:
4. Smart Multi-Field Parser
New files:
/src/exchanges/SmartExchangeParser.h/src/exchanges/SmartExchangeParser.cppTR4W's
ParseArray()equivalent - detect field types and reorder:5. Context-Sensitive Help (F1 Key)
Add F1 key handler to exchange field:
6. Exchange Statistics
Add Tools menu item: "Exchange Statistics"
Show:
Testing Checklist
Deliverable: TR4W-equivalent sophistication; forgiving parser; comprehensive validation
Files to Create
Phase 4
Phase 5
/src/ui/dialogs/ExchangeMemoryDialog.h/src/ui/dialogs/ExchangeMemoryDialog.cppPhase 6
/src/contests/ContestResourceLoader.h/src/contests/ContestResourceLoader.cpp/src/exchanges/SmartExchangeParser.h/src/exchanges/SmartExchangeParser.cpp/resources/contests/WFD_sections.json/resources/contests/ARRL_sections.json/resources/contests/RAC_sections.json/resources/contests/CQ_zones.jsonFiles to Modify
Phase 4
/src/ui/MainWindow.cpponCallsignChanged()autoPopulateExchange()/src/ui/MainWindow.h/src/utils/AppSettings.hgetAutoFocusThreshold(),getAutoSpaceEnabled(),getExchangeOverwriteMode()/src/utils/AppSettings.cppPhase 5
/src/CMakeLists.txt/src/ui/MainWindow.cppPhase 6
/src/contests/WinterFieldDayContest.cpp/src/CMakeLists.txt/src/ui/MainWindow.cppSuccess Metrics
Phase 4
Phase 5
Phase 6
References
Original Plan:
~/.claude/plans/wild-scribbling-shore.mdCompleted Work:
TR4W Reference (for feature parity):
/Users/toms/projects/TR4W/tr4w/src/trdos/LOGEDIT.PAS(line 2207 - InitialExchangeEntry)/Users/toms/projects/TR4W/tr4w/src/trdos/LOGSTUFF.PAS(line 8516 - ProcessExchange)/Users/toms/projects/TR4W/tr4w/src/MainUnit.pas(exchange UI handling)TR4QT Codebase:
/src/ui/MainWindow.cpp(lines 1258-1372, 1710-1771)/src/contests/ContestBase.h(exchange API)/src/contests/WinterFieldDayContest.cpp(complex validation example)Implementation Strategy
Recommended order:
Total: 4-7 weeks for complete TR4W-equivalent exchange system
Milestones: