Working through QUERY MSG [id] and MSG commands to make it easier to work with the inbox
This commit is contained in:
parent
e0838a2164
commit
da41991171
219
mainwindow.cpp
219
mainwindow.cpp
@ -5728,7 +5728,7 @@ void MainWindow::addMessageText(QString text, bool clear, bool selectFirstPlaceh
|
||||
c.insertText(text);
|
||||
|
||||
if(selectFirstPlaceholder){
|
||||
auto match = QRegularExpression("(\\[.+\\])").match(ui->extFreeTextMsgEdit->toPlainText());
|
||||
auto match = QRegularExpression("(\\[[^\\]]+\\])").match(ui->extFreeTextMsgEdit->toPlainText());
|
||||
if(match.hasMatch()){
|
||||
c.setPosition(match.capturedStart());
|
||||
c.setPosition(match.capturedEnd(), QTextCursor::KeepAnchor);
|
||||
@ -6949,8 +6949,8 @@ void MainWindow::sendHeartbeat(){
|
||||
processTxQueue();
|
||||
}
|
||||
|
||||
void MainWindow::sendHeartbeatAck(QString to, int snr){
|
||||
auto message = QString("%1 ACK %2").arg(to).arg(Varicode::formatSNR(snr));
|
||||
void MainWindow::sendHeartbeatAck(QString to, int snr, QString extra){
|
||||
auto message = QString("%1 ACK %2 %3").arg(to).arg(Varicode::formatSNR(snr)).arg(extra).trimmed();
|
||||
|
||||
auto f = m_config.heartbeat_anywhere() ? -1 : findFreeFreqOffset(500, 1000, 50);
|
||||
|
||||
@ -7357,7 +7357,7 @@ void MainWindow::buildQueryMenu(QMenu * menu, QString call){
|
||||
});
|
||||
#endif
|
||||
|
||||
auto alertAction = menu->addAction(QString("%1>[MESSAGE] - Please save this message or relay it to its destination").arg(call).trimmed());
|
||||
auto alertAction = menu->addAction(QString("%1>[MESSAGE] - Please relay this message to its destination").arg(call).trimmed());
|
||||
alertAction->setDisabled(isAllCall);
|
||||
connect(alertAction, &QAction::triggered, this, [this](){
|
||||
|
||||
@ -7509,19 +7509,6 @@ void MainWindow::buildQueryMenu(QMenu * menu, QString call){
|
||||
if(m_config.transmit_directed()) toggleTx(true);
|
||||
});
|
||||
|
||||
auto tuAction = menu->addAction(QString("%1 TU - Thank You").arg(call).trimmed());
|
||||
connect(tuAction, &QAction::triggered, this, [this](){
|
||||
|
||||
QString selectedCall = callsignSelected();
|
||||
if(selectedCall.isEmpty()){
|
||||
return;
|
||||
}
|
||||
|
||||
addMessageText(QString("%1 TU").arg(selectedCall), true);
|
||||
|
||||
if(m_config.transmit_directed()) toggleTx(true);
|
||||
});
|
||||
|
||||
auto sevenThreeAction = menu->addAction(QString("%1 73 - I send my best regards").arg(call).trimmed());
|
||||
connect(sevenThreeAction, &QAction::triggered, this, [this](){
|
||||
|
||||
@ -9696,10 +9683,13 @@ void MainWindow::processCommandActivity() {
|
||||
c.movePosition(QTextCursor::StartOfBlock);
|
||||
c.movePosition(QTextCursor::EndOfBlock, QTextCursor::KeepAnchor);
|
||||
qDebug() << "should display directed message, erasing last rx activity line..." << c.selectedText();
|
||||
c.removeSelectedText();
|
||||
c.deletePreviousChar();
|
||||
c.deletePreviousChar();
|
||||
/*
|
||||
c.deleteChar();
|
||||
c.deleteChar();
|
||||
*/
|
||||
}
|
||||
|
||||
// log it to the display!
|
||||
@ -9841,14 +9831,9 @@ void MainWindow::processCommandActivity() {
|
||||
|
||||
// otherwise, as long as we're not an ACK...alert the user and either send an ACK or Message
|
||||
} else if(!d.text.startsWith("ACK")) {
|
||||
QStringList calls;
|
||||
QString callDePattern = {R"(\sDE\s(?<callsign>\b(?<prefix>[A-Z0-9]{1,4}\/)?(?<base>([0-9A-Z])?([0-9A-Z])([0-9])([A-Z])?([A-Z])?([A-Z])?)(?<suffix>\/[A-Z0-9]{1,4})?)\b)"};
|
||||
QRegularExpression re(callDePattern);
|
||||
auto iter = re.globalMatch(text);
|
||||
while(iter.hasNext()){
|
||||
auto match = iter.next();
|
||||
calls.prepend(match.captured("callsign"));
|
||||
}
|
||||
|
||||
// parse out the callsign path
|
||||
auto calls = parseRelayPathCallsigns(d.from, d.text);
|
||||
|
||||
// put these third party calls in the heard list
|
||||
foreach(auto call, calls){
|
||||
@ -9862,7 +9847,6 @@ void MainWindow::processCommandActivity() {
|
||||
logCallActivity(cd, false);
|
||||
}
|
||||
|
||||
calls.prepend(d.from);
|
||||
d.relayPath = calls.join('>');
|
||||
|
||||
reply = QString("%1 ACK").arg(d.relayPath);
|
||||
@ -9883,7 +9867,7 @@ void MainWindow::processCommandActivity() {
|
||||
rd.bits = d.bits;
|
||||
rd.cmd = first;
|
||||
rd.freq = d.freq;
|
||||
rd.from = d.relayPath;
|
||||
rd.from = d.relayPath; // is this correct?
|
||||
rd.text = d.text;
|
||||
rd.to = d.to;
|
||||
rd.utcTimestamp = d.utcTimestamp;
|
||||
@ -9893,12 +9877,16 @@ void MainWindow::processCommandActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
#if STORE_RELAY_MSGS_TO_INBOX
|
||||
// if we make it here, this is a message
|
||||
addCommandToMyInbox(d);
|
||||
#endif
|
||||
|
||||
#if ALERT_ON_NEW_MSG
|
||||
QTimer::singleShot(500, this, [this, d](){
|
||||
MessageBox::information_message(this, QString("A new message was received at %1 UTC from %2").arg(d.utcTimestamp.time().toString()).arg(d.from));
|
||||
});
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -9943,19 +9931,69 @@ void MainWindow::processCommandActivity() {
|
||||
// PROCESS ACTIVE HEARTBEAT
|
||||
// if we have auto reply enabled and we are heartbeating and selcall is not enabled
|
||||
else if (d.cmd == " HB" && ui->autoReplyButton->isChecked() && ui->hbMacroButton->isChecked() && m_hbInterval > 0){
|
||||
sendHeartbeatAck(d.from, d.snr);
|
||||
|
||||
// check to see if we have a message for a station who is heartbeating
|
||||
QString extra;
|
||||
auto mid = getNextMessageIdForCallsign(d.from);
|
||||
if(mid != -1){
|
||||
extra = QString("MSG ID %1").arg(mid);
|
||||
}
|
||||
|
||||
sendHeartbeatAck(d.from, d.snr, extra);
|
||||
|
||||
if(isAllCall){
|
||||
// since all pings are technically @ALLCALL, let's bump the allcall cache here...
|
||||
m_txAllcallCommandCache.insert(d.from, new QDateTime(now), 5);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// PROCESS MSG
|
||||
else if (d.cmd == " MSG"){
|
||||
|
||||
auto segs = d.text.split(" ");
|
||||
if(segs.isEmpty()){
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
auto mid = segs.first().toInt(&ok);
|
||||
if(!ok){
|
||||
continue;
|
||||
}
|
||||
|
||||
segs.removeFirst();
|
||||
if(segs.isEmpty()){
|
||||
continue;
|
||||
}
|
||||
|
||||
auto text = segs.join(" ");
|
||||
|
||||
qDebug() << "adding message" << mid << "to inbox" << text;
|
||||
|
||||
auto calls = parseRelayPathCallsigns(d.from, text);
|
||||
|
||||
d.cmd = " MSG ";
|
||||
d.relayPath = calls.join(">");
|
||||
d.text = text;
|
||||
|
||||
addCommandToMyInbox(d);
|
||||
|
||||
// make sure this is explicit
|
||||
continue;
|
||||
}
|
||||
|
||||
// PROCESS ACKS
|
||||
else if (d.cmd == " ACK"){
|
||||
qDebug() << "skipping incoming ack" << d.text;
|
||||
|
||||
// make sure this is explicit
|
||||
continue;
|
||||
}
|
||||
|
||||
// PROCESS BUFFERED CMD
|
||||
else if (d.cmd == " CMD" && ui->autoReplyButton->isChecked()){
|
||||
else if (d.cmd == " CMD"){
|
||||
qDebug() << "skipping incoming command" << d.text;
|
||||
|
||||
// make sure this is explicit
|
||||
@ -9963,7 +10001,7 @@ void MainWindow::processCommandActivity() {
|
||||
}
|
||||
|
||||
// PROCESS BUFFERED QUERY
|
||||
else if (d.cmd == " QUERY" && ui->autoReplyButton->isChecked()){
|
||||
else if (d.cmd == " QUERY"){
|
||||
auto who = d.from;
|
||||
|
||||
QStringList segs = d.text.split(" ");
|
||||
@ -10002,7 +10040,12 @@ void MainWindow::processCommandActivity() {
|
||||
continue;
|
||||
}
|
||||
|
||||
reply = QString("%1>MSG %2 %3 DE %4");
|
||||
// mark as delivered (so subsequent HBs and QUERY MSGS don't receive this message)
|
||||
msg.setType("DELIVERED");
|
||||
inbox.set(mid, msg);
|
||||
|
||||
// and reply
|
||||
reply = QString("%1 MSG %2 %3 DE %4");
|
||||
reply = reply.arg(who);
|
||||
reply = reply.arg(mid);
|
||||
reply = reply.arg(text);
|
||||
@ -10014,21 +10057,11 @@ void MainWindow::processCommandActivity() {
|
||||
else if (d.cmd == " QUERY MSGS" && ui->autoReplyButton->isChecked()){
|
||||
auto who = d.from;
|
||||
|
||||
auto inbox = Inbox(inboxPath());
|
||||
if(!inbox.open()){
|
||||
continue;
|
||||
}
|
||||
|
||||
// if this is an allcall or a directed call, check to see if we have a stored message for user.
|
||||
// we reply yes if the user would be able to retreive a stored message
|
||||
auto v = inbox.values("STORE", "$.params.TO", who, 0, 10);
|
||||
foreach(auto pair, v){
|
||||
auto params = pair.second.params();
|
||||
auto text = params.value("TEXT").toString().trimmed();
|
||||
if(!text.isEmpty()){
|
||||
reply = QString("%1 YES MSG %2").arg(who).arg(pair.first);
|
||||
break;
|
||||
}
|
||||
auto mid = getNextMessageIdForCallsign(who);
|
||||
if(mid != -1){
|
||||
reply = QString("%1 YES MSG ID %2").arg(who).arg(mid);
|
||||
}
|
||||
|
||||
// if this is not an allcall and we have no messages, reply no.
|
||||
@ -10193,47 +10226,81 @@ void MainWindow::refreshInboxCounts(){
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::addCommandToMyInbox(CommandDetail d){
|
||||
int MainWindow::addCommandToMyInbox(CommandDetail d){
|
||||
// local cache for inbox count
|
||||
m_rxInboxCountCache[d.from] = m_rxInboxCountCache.value(d.from, 0) + 1;
|
||||
|
||||
// add it to my unread inbox
|
||||
addCommandToInboxStorage("UNREAD", d);
|
||||
return addCommandToInboxStorage("UNREAD", d);
|
||||
}
|
||||
|
||||
void MainWindow::addCommandToInboxStorage(QString type, CommandDetail d){
|
||||
int MainWindow::addCommandToInboxStorage(QString type, CommandDetail d){
|
||||
// inbox:
|
||||
auto inbox = Inbox(inboxPath());
|
||||
if(inbox.open()){
|
||||
auto df = dialFrequency();
|
||||
|
||||
QMap<QString, QVariant> v = {
|
||||
{"UTC", QVariant(d.utcTimestamp.toString("yyyy-MM-dd hh:mm:ss"))},
|
||||
{"TO", QVariant(d.to)},
|
||||
{"FROM", QVariant(d.from)},
|
||||
{"PATH", QVariant(d.relayPath)},
|
||||
{"DIAL", QVariant((quint64)df)},
|
||||
{"TDRIFT", QVariant(d.tdrift)},
|
||||
{"OFFSET", QVariant(d.freq)},
|
||||
{"CMD", QVariant(d.cmd)},
|
||||
{"SNR", QVariant(d.snr)},
|
||||
};
|
||||
|
||||
if(!d.grid.isEmpty()){
|
||||
v["GRID"] = QVariant(d.grid);
|
||||
}
|
||||
|
||||
if(!d.extra.isEmpty()){
|
||||
v["EXTRA"] = QVariant(d.extra);
|
||||
}
|
||||
|
||||
if(!d.text.isEmpty()){
|
||||
v["TEXT"] = QVariant(d.text);
|
||||
}
|
||||
|
||||
auto m = Message(type, "", v);
|
||||
inbox.append(m);
|
||||
if(!inbox.open()){
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto df = dialFrequency();
|
||||
|
||||
QMap<QString, QVariant> v = {
|
||||
{"UTC", QVariant(d.utcTimestamp.toString("yyyy-MM-dd hh:mm:ss"))},
|
||||
{"TO", QVariant(d.to)},
|
||||
{"FROM", QVariant(d.from)},
|
||||
{"PATH", QVariant(d.relayPath)},
|
||||
{"DIAL", QVariant((quint64)df)},
|
||||
{"TDRIFT", QVariant(d.tdrift)},
|
||||
{"OFFSET", QVariant(d.freq)},
|
||||
{"CMD", QVariant(d.cmd)},
|
||||
{"SNR", QVariant(d.snr)},
|
||||
};
|
||||
|
||||
if(!d.grid.isEmpty()){
|
||||
v["GRID"] = QVariant(d.grid);
|
||||
}
|
||||
|
||||
if(!d.extra.isEmpty()){
|
||||
v["EXTRA"] = QVariant(d.extra);
|
||||
}
|
||||
|
||||
if(!d.text.isEmpty()){
|
||||
v["TEXT"] = QVariant(d.text);
|
||||
}
|
||||
|
||||
auto m = Message(type, "", v);
|
||||
|
||||
return inbox.append(m);
|
||||
}
|
||||
|
||||
int MainWindow::getNextMessageIdForCallsign(QString callsign){
|
||||
auto inbox = Inbox(inboxPath());
|
||||
if(!inbox.open()){
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto v = inbox.values("STORE", "$.params.TO", callsign, 0, 10);
|
||||
foreach(auto pair, v){
|
||||
auto params = pair.second.params();
|
||||
auto text = params.value("TEXT").toString().trimmed();
|
||||
if(!text.isEmpty()){
|
||||
return pair.first;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
QStringList MainWindow::parseRelayPathCallsigns(QString from, QString text){
|
||||
QStringList calls;
|
||||
QString callDePattern = {R"(\sDE\s(?<callsign>\b(?<prefix>[A-Z0-9]{1,4}\/)?(?<base>([0-9A-Z])?([0-9A-Z])([0-9])([A-Z])?([A-Z])?([A-Z])?)(?<suffix>\/[A-Z0-9]{1,4})?)\b)"};
|
||||
QRegularExpression re(callDePattern);
|
||||
auto iter = re.globalMatch(text);
|
||||
while(iter.hasNext()){
|
||||
auto match = iter.next();
|
||||
calls.prepend(match.captured("callsign"));
|
||||
}
|
||||
calls.prepend(from);
|
||||
return calls;
|
||||
}
|
||||
|
||||
void MainWindow::processAlertReplyForCommand(CommandDetail d, QString from, QString cmd){
|
||||
|
@ -284,7 +284,7 @@ private slots:
|
||||
void buildCQMenu(QMenu *menu);
|
||||
void buildRepeatMenu(QMenu *menu, QPushButton * button, int * interval);
|
||||
void sendHeartbeat();
|
||||
void sendHeartbeatAck(QString to, int snr);
|
||||
void sendHeartbeatAck(QString to, int snr, QString extra);
|
||||
void on_hbMacroButton_toggled(bool checked);
|
||||
void on_hbMacroButton_clicked();
|
||||
void sendCQ(bool repeat=false);
|
||||
@ -952,8 +952,10 @@ private:
|
||||
void processCommandActivity();
|
||||
QString inboxPath();
|
||||
void refreshInboxCounts();
|
||||
void addCommandToMyInbox(CommandDetail d);
|
||||
void addCommandToInboxStorage(QString type, CommandDetail d);
|
||||
int addCommandToMyInbox(CommandDetail d);
|
||||
int addCommandToInboxStorage(QString type, CommandDetail d);
|
||||
int getNextMessageIdForCallsign(QString callsign);
|
||||
QStringList parseRelayPathCallsigns(QString from, QString text);
|
||||
void processAlertReplyForCommand(CommandDetail d, QString from, QString cmd);
|
||||
void processSpots();
|
||||
void processTxQueue();
|
||||
|
81
varicode.cpp
81
varicode.cpp
@ -45,73 +45,71 @@ QString alphanumeric = {"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ /@"}; // callsign
|
||||
QMap<QString, int> directed_cmds = {
|
||||
// any changes here need to be made also in the directed regular xpression for parsing
|
||||
// ?*^&@
|
||||
{" HB", -1 }, // this is my heartbeat (unused except for faux processing of HBs as directed commands)
|
||||
|
||||
{" SNR?", 0 }, // query snr
|
||||
{"?", 0 }, // compat
|
||||
{" SNR?", 0 }, // query snr
|
||||
{"?", 0 }, // compat
|
||||
|
||||
{" QTH?", 1 }, // query qth
|
||||
//{" ", 1 }, // unused
|
||||
//{" ", 2 }, // unused
|
||||
|
||||
//{" ", 2 }, // unused
|
||||
{" HEARING?", 3 }, // query station calls heard
|
||||
|
||||
{" HEARING?", 3 }, // query station calls heard
|
||||
{" GRID?", 4 }, // query grid
|
||||
|
||||
{" GRID?", 4 }, // query grid
|
||||
{">", 5 }, // relay message
|
||||
|
||||
{">", 5 }, // relay message
|
||||
{" STATUS?", 6 }, // query idle message
|
||||
|
||||
{" STATUS?", 6 }, // query idle message
|
||||
{" STATUS", 7 }, // this is my status
|
||||
|
||||
{" STATUS", 7 }, // this is my status
|
||||
{" HEARING", 8 }, // these are the stations i'm hearing
|
||||
|
||||
{" HEARING", 8 }, // these are the stations i'm hearing
|
||||
{" MSG", 9 }, // this is a complete message
|
||||
|
||||
{" TU", 9 }, // thank you
|
||||
{" MSG TO:", 10 }, // store message at a station
|
||||
|
||||
{" HB", -1 }, // this is my heartbeat (unused except for faux processing of HBs as directed commands)
|
||||
{" QUERY", 11 }, // generic query
|
||||
|
||||
{" MSG TO:", 10 }, // store message at a station
|
||||
{" QUERY MSGS", 12 }, // do you have any stored messages?
|
||||
|
||||
{" QUERY", 11 }, // generic query
|
||||
{" QUERY CALL", 13 }, // can you transmit a ping to callsign?
|
||||
|
||||
{" QUERY MSGS", 12 }, // do you have any stored messages?
|
||||
{" APRS:", 14 }, // send an aprs packet
|
||||
|
||||
{" QUERY CALL", 13 }, // can you transmit a ping to callsign?
|
||||
{" GRID", 15 }, // this is my current grid locator
|
||||
|
||||
{" APRS:", 14 }, // send an aprs packet
|
||||
{" QTH?", 16 }, // what is your qth message?
|
||||
{" QTH", 17 }, // this is my qth message
|
||||
|
||||
{" GRID", 15 }, // this is my current grid locator
|
||||
{" FB", 18 }, // fine business
|
||||
{" HW CPY?", 19 }, // how do you copy?
|
||||
{" SK", 20 }, // end of contact
|
||||
{" RR", 21 }, // roger roger
|
||||
|
||||
//{" ", 16 }, // unused
|
||||
{" QSL?", 22 }, // do you copy?
|
||||
{" QSL", 23 }, // i copy
|
||||
|
||||
{" QTH", 17 }, // this is my qth message
|
||||
{" CMD", 24 }, // command
|
||||
|
||||
{" FB", 18 }, // fine business
|
||||
{" HW CPY?", 19 }, // how do you copy?
|
||||
{" SK", 20 }, // end of contact
|
||||
{" RR", 21 }, // roger roger
|
||||
{" QSL?", 22 }, // do you copy?
|
||||
{" QSL", 23 }, // i copy
|
||||
|
||||
{" CMD", 24 }, // open ended command
|
||||
|
||||
{" SNR", 25 }, // seen a station at the provided snr
|
||||
{" NO", 26 }, // negative confirm
|
||||
{" YES", 27 }, // confirm
|
||||
{" 73", 28 }, // best regards, end of contact
|
||||
{" ACK", 29 }, // acknowledge
|
||||
{" AGN?", 30 }, // repeat message
|
||||
{" ", 31 }, // send freetext (weird artifact)
|
||||
{" ", 31 }, // send freetext
|
||||
{" SNR", 25 }, // seen a station at the provided snr
|
||||
{" NO", 26 }, // negative confirm
|
||||
{" YES", 27 }, // confirm
|
||||
{" 73", 28 }, // best regards, end of contact
|
||||
{" ACK", 29 }, // acknowledge
|
||||
{" AGN?", 30 }, // repeat message
|
||||
{" ", 31 }, // send freetext (weird artifact)
|
||||
{" ", 31 }, // send freetext
|
||||
};
|
||||
|
||||
// commands allowed to be processed
|
||||
QSet<int> allowed_cmds = {-1, 0, 1, /*2,*/ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /*16,*/ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
QSet<int> allowed_cmds = {-1, 0, /*1,*/ /*2,*/ 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
|
||||
|
||||
// commands that result in an autoreply (which can be relayed)
|
||||
QSet<int> autoreply_cmds = {0, 1, 3, 4, 6, 10, 11, 12, 13, 30};
|
||||
QSet<int> autoreply_cmds = {0, 3, 4, 6, 9, 11, 12, 13, 16, 30};
|
||||
|
||||
// commands that should be buffered
|
||||
QSet<int> buffered_cmds = {3, 5, /*6,*/ /*7,*/ 10, 11, 12, 13, 14, 15, 24};
|
||||
QSet<int> buffered_cmds = {5, /*6,*/ /*7,*/ 9, 10, 11, 12, 13, 14, 15, 24};
|
||||
|
||||
// commands that may include an SNR value
|
||||
QSet<int> snr_cmds = {25, 29};
|
||||
@ -119,6 +117,7 @@ QSet<int> snr_cmds = {25, 29};
|
||||
// commands that are checksummed and their crc size
|
||||
QMap<int, int> checksum_cmds = {
|
||||
{ 5, 16 },
|
||||
{ 9, 16 },
|
||||
{ 10, 16 },
|
||||
{ 11, 16 },
|
||||
{ 12, 16 },
|
||||
@ -129,7 +128,7 @@ QMap<int, int> checksum_cmds = {
|
||||
};
|
||||
|
||||
QString callsign_pattern = QString("(?<callsign>[@]?[A-Z0-9/]+)");
|
||||
QString optional_cmd_pattern = QString("(?<cmd>\\s?(?:AGN[?]|QSL[?]|HW CPY[?]|APRS[:]|MSG TO[:]|SNR[?]|QTH[?]|GRID[?]|STATUS[?]|HEARING[?]|(?:(?:STATUS|HEARING|QUERY CALL|QUERY MSGS|QUERY|CMD|ACK|73|YES|NO|SNR|QSL|RR|SK|FB|QTH|GRID|TU)(?=[ ]|$))|[?> ]))?");
|
||||
QString optional_cmd_pattern = QString("(?<cmd>\\s?(?:AGN[?]|QSL[?]|HW CPY[?]|APRS[:]|MSG TO[:]|SNR[?]|QTH[?]|GRID[?]|STATUS[?]|HEARING[?]|(?:(?:STATUS|HEARING|QUERY CALL|QUERY MSGS|QUERY|CMD|MSG|ACK|73|YES|NO|SNR|QSL|RR|SK|FB|QTH|GRID)(?=[ ]|$))|[?> ]))?");
|
||||
QString optional_grid_pattern = QString("(?<grid>\\s?[A-R]{2}[0-9]{2})?");
|
||||
QString optional_extended_grid_pattern = QString("^(?<grid>\\s?(?:[A-R]{2}[0-9]{2}(?:[A-X]{2}(?:[0-9]{2})?)*))?");
|
||||
QString optional_num_pattern = QString("(?<num>(?<=SNR|ACK)\\s?[-+]?(?:3[01]|[0-2]?[0-9]))?");
|
||||
|
Loading…
Reference in New Issue
Block a user