Added background thread to compute message frames

This commit is contained in:
Jordan Sherer 2018-10-02 09:44:46 -04:00
parent 862e702b2d
commit 2cb1665e2e
4 changed files with 373 additions and 326 deletions

View File

@ -263,28 +263,6 @@ namespace
return roundDown + multiple;
}
QString rstrip(const QString& str) {
int n = str.size() - 1;
for (; n >= 0; --n) {
if (str.at(n).isSpace()) {
continue;
}
return str.left(n + 1);
}
return "";
}
QString lstrip(const QString& str) {
int len = str.size();
for (int n = 0; n < len; n++) {
if(str.at(n).isSpace()){
continue;
}
return str.mid(n);
}
return "";
}
void setTextEditFont(QTextEdit *edit, QFont font){
edit->setFont(font);
edit->setFontFamily(font.family());
@ -1417,6 +1395,10 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
});
*/
m_txTextDirtyDebounce.setSingleShot(true);
m_txTextDirtyDebounce.setInterval(100);
connect(&m_txTextDirtyDebounce, &QTimer::timeout, this, &MainWindow::buildMessageFramesAndUpdateCountDisplay);
QTimer::singleShot(0, this, &MainWindow::initializeDummyData);
// this must be the last statement of constructor
@ -6060,7 +6042,7 @@ void MainWindow::createMessage(QString const& text){
}
void MainWindow::createMessageTransmitQueue(QString const& text){
auto frames = buildFT8MessageFrames(text);
auto frames = buildMessageFrames(text);
m_txFrameQueue.append(frames);
m_txFrameCount = frames.length();
@ -6135,16 +6117,11 @@ int MainWindow::currentFreqOffset(){
return ui->RxFreqSpinBox->value();
}
int MainWindow::countFT8MessageFrames(QString const& text){
return buildFT8MessageFrames(text).length();
int MainWindow::countMessageFrames(QString const& text){
return buildMessageFrames(text).length();
}
QStringList MainWindow::buildFT8MessageFrames(QString const& text){
#define ALLOW_SEND_COMPOUND 1
#define AUTO_PREPEND_DIRECTED 1
QStringList frames;
QStringList MainWindow::buildMessageFrames(const QString &text){
// prepare selected callsign for directed message
QString selectedCall = callsignSelected();
@ -6157,226 +6134,10 @@ QStringList MainWindow::buildFT8MessageFrames(QString const& text){
basecall = "<....>";
}
foreach(QString line, text.split(QRegExp("[\\r\\n]"), QString::SkipEmptyParts)){
// once we find a directed call, data encode the rest of the line.
bool hasDirected = false;
// do the same for when we have sent data...
bool hasData = false;
// remove our callsign from the start of the line...
if(line.startsWith(mycall + ":") || line.startsWith(mycall + " ")){
line = lstrip(line.mid(mycall.length() + 1));
}
if(line.startsWith(basecall + ":") || line.startsWith(basecall + " ")){
line = lstrip(line.mid(basecall.length() + 1));
}
// remove trailing whitespace as long as there are characters left afterwards
auto rline = rstrip(line);
if(!rline.isEmpty()){
line = rline;
}
#if AUTO_PREPEND_DIRECTED
// see if we need to prepend the directed call to the line...
// if we have a selected call and the text doesn't start with that call...
// and if this isn't a raw message (starting with "<")... then...
if(!selectedCall.isEmpty() && !line.startsWith(selectedCall) && !line.startsWith("<")){
auto calls = Varicode::parseCallsigns(line);
bool lineStartsWithBaseCall = (
line.startsWith("ALLCALL") ||
line.startsWith("BEACON") ||
Varicode::startsWithCQ(line)
);
bool lineStartsWithStandardCall = !calls.isEmpty() && line.startsWith(calls.first());
if(lineStartsWithBaseCall || lineStartsWithStandardCall){
// pass
} else {
// if the message doesn't start with a base call
// and if there are no other callsigns in this message
// or if the first callsign in the message isn't at the beginning...
// then we should be auto-prefixing this line with the selected call
line = QString("%1 %2").arg(selectedCall).arg(line);
}
}
#endif
while(line.size() > 0){
QString frame;
bool useStd = false;
bool useBcn = false;
#if ALLOW_SEND_COMPOUND
bool useCmp = false;
#endif
bool useDir = false;
bool useDat = false;
bool isFree = false;
QString stdFrame = parseFT8Message(line, &isFree);
int l = 0;
QString bcnFrame = Varicode::packBeaconMessage(line, mycall, &l);
#if ALLOW_SEND_COMPOUND
int o = 0;
QString cmpFrame = Varicode::packCompoundMessage(line, &o);
#endif
int n = 0;
QString dirCmd;
QString dirTo;
QString dirNum;
QString dirFrame = Varicode::packDirectedMessage(line, basecall, &dirTo, &dirCmd, &dirNum, &n);
bool dirToCompound = dirTo.contains("/");
int m = 0;
QString datFrame = Varicode::packDataMessage(line.left(24) + "\x04", &m); // 66 / 3 + 2 = 22 (maximum number of 3bit chars we could possibly stuff in here plus 2 for good measure :P)
// if this parses to a standard FT8 free text message
// but it can be parsed as a directed message, then we
// should send the directed version. if we've already sent
// a directed message or a data frame, we will only follow it
// with more data frames.
if(isFree && !hasDirected && !hasData && l > 0){
useBcn = true;
hasDirected = false;
frame = bcnFrame;
}
#if ALLOW_SEND_COMPOUND
else if(isFree && !hasDirected && !hasData && o > 0){
useCmp = true;
hasDirected = false;
frame = cmpFrame;
}
#endif
else if(isFree && !hasDirected && !hasData && n > 0){
useDir = true;
hasDirected = true;
frame = dirFrame;
}
else if ((isFree || hasDirected) && m > 0) {
useDat = true;
hasData = true;
frame = datFrame;
} else {
useStd = true;
frame = stdFrame;
}
if(useStd){
if(frame.isEmpty()){
break;
}
frames.append(frame);
if(!line.startsWith(frame)){
line = (
line.left(frame.length()).replace(':', ' ') + // is this the only case where we could have a mismatch?
line.mid(frame.length())
).trimmed();
}
line = line.mid(frame.length()).trimmed();
}
if(useBcn){
frames.append(frame);
line = line.mid(l);
}
#if ALLOW_SEND_COMPOUND
if(useCmp){
frames.append(frame);
line = line.mid(o);
}
#endif
if(useDir){
/**
* We have a few special cases when we are sending to a compound call, or our call is a compound call, or both.
* CASE 0: Non-compound: KN4CRD: J1Y ACK
* -> One standard directed message frame
*
* CASE 1: Compound From: KN4CRD/P: J1Y ACK
* -> One standard compound frame, followed by a standard directed message frame with placeholder
* -> The second standard directed frame _could_ be replaced with a compound directed frame
* -> <KN4CRD/P EM73> then <....>: J1Y ACK
* -> <KN4CRD/P EM73> then <J1Y ACK>
*
* CASE 2: Compound To: KN4CRD: J1Y/P ACK
* -> One standard compound frame, followed by a compound directed frame
* -> <KN4CRD EM73> then <J1Y/P ACK>
*
* CASE 3: Compound From & To: KN4CRD/P: J1Y/P ACK
* -> One standard compound frame, followed by a compound directed frame
* -> <KN4CRD/P EM73> then <J1Y/P ACK>
**/
bool shouldUseStandardFrame = true;
if(compound || dirToCompound){
// Cases 1, 2, 3 all send a standard compound frame first...
QString deCompoundMessage = QString("<%1 %2>").arg(mycall).arg(mygrid);
QString deCompoundFrame = Varicode::packCompoundMessage(deCompoundMessage, nullptr);
if(!deCompoundFrame.isEmpty()){
frames.append(deCompoundFrame);
}
// Followed, by a standard OR compound directed message...
QString dirCompoundMessage = QString("<%1%2%3>").arg(dirTo).arg(dirCmd).arg(dirNum);
QString dirCompoundFrame = Varicode::packCompoundMessage(dirCompoundMessage, nullptr);
if(!dirCompoundFrame.isEmpty()){
frames.append(dirCompoundFrame);
}
shouldUseStandardFrame = false;
}
if(shouldUseStandardFrame) {
// otherwise, just send the standard directed frame
frames.append(frame);
}
line = line.mid(n);
// generate a checksum for buffered commands with line data
if(Varicode::isCommandBuffered(dirCmd) && !line.isEmpty()){
qDebug() << "generating checksum for line" << line << line.mid(1);
// strip leading whitespace after a buffered directed command
line = lstrip(line);
qDebug() << "before:" << line;
int checksumSize = Varicode::isCommandChecksumed(dirCmd);
if(checksumSize == 32){
line = line + " " + Varicode::checksum32(line);
} else if (checksumSize == 16) {
line = line + " " + Varicode::checksum16(line);
} else if (checksumSize == 0) {
// pass
}
qDebug() << "after:" << line;
}
// APRS:
if(dirCmd.trimmed() == "APRS:" && !m_aprsClient->isPasscodeValid()){
MessageBox::warning_message(this, tr ("Please enter a valid APRS passcode in the settings to send an APRS packet."));
}
}
if(useDat){
frames.append(frame);
line = line.mid(m);
}
}
}
auto frames = Varicode::buildMessageFrames(mycall, basecall, mygrid, compound, selectedCall, text);
#if 1
qDebug() << "parsed frames:";
qDebug() << "frames:";
foreach(auto frame, frames){
auto dt = DecodedText(frame);
qDebug() << "->" << frame << dt.message() << Varicode::frameTypeString(dt.frameType());
@ -6386,60 +6147,6 @@ QStringList MainWindow::buildFT8MessageFrames(QString const& text){
return frames;
}
QString MainWindow::parseFT8Message(QString input, bool *isFree){
if(isFree) *isFree = true;
return input;
#if 0
char message[29];
char msgsent[29];
char volatile ft8msgbits[75 + 12];
int volatile itone[NUM_ISCAT_SYMBOLS];
QByteArray ba = input.toLocal8Bit();
ba2msg(ba,message);
qint32 i3bit = 0;
bool bcontest = false;
char MyGrid[6];
strncpy(MyGrid, (m_config.my_grid()+" ").toLatin1(),6);
genft8_(message, MyGrid, &bcontest, &i3bit, msgsent, const_cast<char *> (ft8msgbits),
const_cast<int *> (itone), 22, 6, 22);
msgsent[22]=0;
// decode the msg bits into 6-bit bytes so we can check to see if its a free text message or not...
// see extractmessage1764.f90 for the original implementation. we could technically add a boolean output
// from the fortran code, but this avoids having to modify that so we can easily apply updates to the
// signal functions in the future without incurring too much cognitive overhead of merge conflicts.
char msgbytes[12];
for(int ibyte = 1; ibyte <= 12; ibyte++){
int itmp = 0;
for(int ibit = 1; ibit <= 6; ibit++){
itmp = (itmp << 1) + (1 & (ft8msgbits[((ibyte-1) * 6 + ibit)-1]));
}
msgbytes[ibyte-1] = itmp;
}
int a = msgbytes[9];
int b = msgbytes[10];
int c = msgbytes[11];
int d = ((a & 15) << 12) + (b << 6) + c;
QString output = QString::fromLatin1(msgsent);
if(isFree){
// TODO: jsherer - lets figure out a better way to detect this for the case:
// KN4CRD 16
// this gets encoded as a standard message, but doesn't seem to make sense as to why...
// see decodedtext.cpp for the alternate decoding side of this...
*isFree = (d >= 32768) || !QRegularExpression("^(CQ|DE|QRZ)\\s").match(output).hasMatch();
}
return output.trimmed();
#endif
}
bool MainWindow::prepareNextMessageFrame()
{
m_i3bit = Varicode::FT8Call;
@ -8997,25 +8704,64 @@ void MainWindow::updateButtonDisplay(){
ui->startTxButton->setText(m_tune ? "Tuning" : QString("Sending (%1/%2)").arg(sent).arg(count));
} else if(m_txTextDirty) {
// TODO: only if text changed
auto text = ui->extFreeTextMsgEdit->toPlainText();
int count = countFT8MessageFrames(text);
if(count > 0){
ui->startTxButton->setText(QString("Send (%1)").arg(count));
ui->startTxButton->setEnabled(true);
auto words = text.split(" ", QString::SkipEmptyParts).length();
auto wpm = QString::number(words/(count/4.0), 'f', 1);
auto cpm = QString::number(text.length()/(count/4.0), 'f', 0);
wpm_label.setText(QString("%1wpm / %2cpm").arg(wpm).arg(cpm));
} else {
ui->startTxButton->setText("Send");
ui->startTxButton->setEnabled(false);
wpm_label.clear();
// TODO: maybe add debounce?
if(m_txTextDirtyDebounce.isActive()){
m_txTextDirtyDebounce.stop();
}
m_txTextDirtyDebounce.start(100);
m_txTextDirty = false;
}
}
void MainWindow::buildMessageFramesAndUpdateCountDisplay(){
qDebug() << "buildMessageFramesAndUpdateCountDisplay";
auto text = ui->extFreeTextMsgEdit->toPlainText();
#if USE_SYNC_FRAME_COUNT
int count = countMessageFrames(text);
updateFrameCountDisplay(text, count);
#else
// prepare selected callsign for directed message
QString selectedCall = callsignSelected();
// prepare compound
bool compound = Radio::is_compound_callsign(m_config.my_callsign());
QString mygrid = m_config.my_grid().left(4);
QString mycall = m_config.my_callsign();
QString basecall = Radio::base_callsign(m_config.my_callsign());
if(basecall != mycall){
basecall = "<....>";
}
BuildMessageFramesThread *t = new BuildMessageFramesThread(
mycall, basecall, mygrid, compound, selectedCall, text
);
connect(t, &BuildMessageFramesThread::finished, t, &QObject::deleteLater);
connect(t, &BuildMessageFramesThread::resultReady, this, [this, text](const QStringList frames){
updateFrameCountDisplay(text, frames.length());
});
t->start();
#endif
}
void MainWindow::updateFrameCountDisplay(QString text, int count){
if(count > 0){
ui->startTxButton->setText(QString("Send (%1)").arg(count));
ui->startTxButton->setEnabled(true);
auto words = text.split(" ", QString::SkipEmptyParts).length();
auto wpm = QString::number(words/(count/4.0), 'f', 1);
auto cpm = QString::number(text.length()/(count/4.0), 'f', 0);
wpm_label.setText(QString("%1wpm / %2cpm").arg(wpm).arg(cpm));
wpm_label.setVisible(true);
} else {
ui->startTxButton->setText("Send");
ui->startTxButton->setEnabled(false);
wpm_label.setVisible(false);
wpm_label.clear();
}
}
@ -9344,7 +9090,7 @@ void MainWindow::processBufferedActivity() {
foreach(auto part, buffer.msgs) {
message.append(part.text);
}
message = rstrip(message);
message = Varicode::rstrip(message);
QString checksum;

View File

@ -95,6 +95,7 @@ class DecodedText;
using namespace std;
typedef std::function<void()> Callback;
class MainWindow : public QMainWindow
{
Q_OBJECT;
@ -294,9 +295,8 @@ private slots:
void on_nextFreeTextMsg_currentTextChanged (QString const&);
void on_extFreeTextMsgEdit_currentTextChanged (QString const&);
int currentFreqOffset();
int countFT8MessageFrames(QString const& text);
QStringList buildFT8MessageFrames(QString const& text);
QString parseFT8Message(QString input, bool *isFree);
int countMessageFrames(QString const& text);
QStringList buildMessageFrames(QString const& text);
bool prepareNextMessageFrame();
bool isFreqOffsetFree(int f, int bw);
int findFreeFreqOffset(int fmin, int fmax, int bw);
@ -383,6 +383,7 @@ private slots:
void expiry_warning_message ();
void not_GA_warning_message ();
void clearCallsignSelected();
void buildMessageFramesAndUpdateCountDisplay();
private:
Q_SIGNAL void initializeAudioOutputStream (QAudioDeviceInfo,
@ -646,7 +647,6 @@ private:
QTimer splashTimer;
QTimer p1Timer;
QTimer beaconTimer;
QTimer selectedCallTimer;
QString m_path;
QString m_baseCall;
@ -728,6 +728,7 @@ private:
bool m_rxDirty;
bool m_rxDisplayDirty;
int m_txFrameCount;
QTimer m_txTextDirtyDebounce;
bool m_txTextDirty;
QString m_lastTxMessage;
QDateTime m_lastTxTime;
@ -877,9 +878,11 @@ private:
void postDecode (bool is_new, QString const& message);
void displayTransmit();
void updateButtonDisplay();
void updateFrameCountDisplay(QString text, int count);
bool isMyCallIncluded(QString const &text);
bool isAllCallIncluded(QString const &text);
QString callsignSelected();
void clearCallsignSelected();
bool isRecentOffset(int offset);
void markOffsetRecent(int offset);
bool isDirectedOffset(int offset, bool *pIsAllCall);
@ -936,7 +939,6 @@ private:
void write_transmit_entry (QString const& file_name);
};
extern int killbyname(const char* progName);
extern void getDev(int* numDevices,char hostAPI_DeviceName[][50],
int minChan[], int maxChan[],

View File

@ -438,6 +438,28 @@ int dbmTomwatts(int dbm){
return iter.value();
}
QString Varicode::rstrip(const QString& str) {
int n = str.size() - 1;
for (; n >= 0; --n) {
if (str.at(n).isSpace()) {
continue;
}
return str.left(n + 1);
}
return "";
}
QString Varicode::lstrip(const QString& str) {
int len = str.size();
for (int n = 0; n < len; n++) {
if(str.at(n).isSpace()){
continue;
}
return str.mid(n);
}
return "";
}
/*
* VARICODE
*/
@ -1642,3 +1664,242 @@ QString Varicode::unpackDataMessage(const QString &text, quint8 *pType){
return unpacked;
}
// TODO: remove the dependence on providing all this data?
QStringList Varicode::buildMessageFrames(
QString const& mycall,
QString const& basecall,
QString const& mygrid,
bool compound,
QString const& selectedCall,
QString const& text
){
#define ALLOW_SEND_COMPOUND 1
#define AUTO_PREPEND_DIRECTED 1
QStringList frames;
foreach(QString line, text.split(QRegExp("[\\r\\n]"), QString::SkipEmptyParts)){
// once we find a directed call, data encode the rest of the line.
bool hasDirected = false;
// do the same for when we have sent data...
bool hasData = false;
// remove our callsign from the start of the line...
if(line.startsWith(mycall + ":") || line.startsWith(mycall + " ")){
line = lstrip(line.mid(mycall.length() + 1));
}
if(line.startsWith(basecall + ":") || line.startsWith(basecall + " ")){
line = lstrip(line.mid(basecall.length() + 1));
}
// remove trailing whitespace as long as there are characters left afterwards
auto rline = rstrip(line);
if(!rline.isEmpty()){
line = rline;
}
#if AUTO_PREPEND_DIRECTED
// see if we need to prepend the directed call to the line...
// if we have a selected call and the text doesn't start with that call...
// and if this isn't a raw message (starting with "<")... then...
if(!selectedCall.isEmpty() && !line.startsWith(selectedCall) && !line.startsWith("<")){
auto calls = Varicode::parseCallsigns(line);
bool lineStartsWithBaseCall = (
line.startsWith("ALLCALL") ||
line.startsWith("BEACON") ||
Varicode::startsWithCQ(line)
);
bool lineStartsWithStandardCall = !calls.isEmpty() && line.startsWith(calls.first());
if(lineStartsWithBaseCall || lineStartsWithStandardCall){
// pass
} else {
// if the message doesn't start with a base call
// and if there are no other callsigns in this message
// or if the first callsign in the message isn't at the beginning...
// then we should be auto-prefixing this line with the selected call
line = QString("%1 %2").arg(selectedCall).arg(line);
}
}
#endif
while(line.size() > 0){
QString frame;
bool useBcn = false;
#if ALLOW_SEND_COMPOUND
bool useCmp = false;
#endif
bool useDir = false;
bool useDat = false;
int l = 0;
QString bcnFrame = Varicode::packBeaconMessage(line, mycall, &l);
#if ALLOW_SEND_COMPOUND
int o = 0;
QString cmpFrame = Varicode::packCompoundMessage(line, &o);
#endif
int n = 0;
QString dirCmd;
QString dirTo;
QString dirNum;
QString dirFrame = Varicode::packDirectedMessage(line, basecall, &dirTo, &dirCmd, &dirNum, &n);
bool dirToCompound = dirTo.contains("/");
int m = 0;
QString datFrame = Varicode::packDataMessage(line.left(24) + "\x04", &m); // 66 / 3 + 2 = 22 (maximum number of 3bit chars we could possibly stuff in here plus 2 for good measure :P)
// if this parses to a standard FT8 free text message
// but it can be parsed as a directed message, then we
// should send the directed version. if we've already sent
// a directed message or a data frame, we will only follow it
// with more data frames.
if(!hasDirected && !hasData && l > 0){
useBcn = true;
hasDirected = false;
frame = bcnFrame;
}
#if ALLOW_SEND_COMPOUND
else if(!hasDirected && !hasData && o > 0){
useCmp = true;
hasDirected = false;
frame = cmpFrame;
}
#endif
else if(!hasDirected && !hasData && n > 0){
useDir = true;
hasDirected = true;
frame = dirFrame;
}
else if (m > 0) {
useDat = true;
hasData = true;
frame = datFrame;
}
if(useBcn){
frames.append(frame);
line = line.mid(l);
}
#if ALLOW_SEND_COMPOUND
if(useCmp){
frames.append(frame);
line = line.mid(o);
}
#endif
if(useDir){
/**
* We have a few special cases when we are sending to a compound call, or our call is a compound call, or both.
* CASE 0: Non-compound: KN4CRD: J1Y ACK
* -> One standard directed message frame
*
* CASE 1: Compound From: KN4CRD/P: J1Y ACK
* -> One standard compound frame, followed by a standard directed message frame with placeholder
* -> The second standard directed frame _could_ be replaced with a compound directed frame
* -> <KN4CRD/P EM73> then <....>: J1Y ACK
* -> <KN4CRD/P EM73> then <J1Y ACK>
*
* CASE 2: Compound To: KN4CRD: J1Y/P ACK
* -> One standard compound frame, followed by a compound directed frame
* -> <KN4CRD EM73> then <J1Y/P ACK>
*
* CASE 3: Compound From & To: KN4CRD/P: J1Y/P ACK
* -> One standard compound frame, followed by a compound directed frame
* -> <KN4CRD/P EM73> then <J1Y/P ACK>
**/
bool shouldUseStandardFrame = true;
if(compound || dirToCompound){
// Cases 1, 2, 3 all send a standard compound frame first...
QString deCompoundMessage = QString("<%1 %2>").arg(mycall).arg(mygrid);
QString deCompoundFrame = Varicode::packCompoundMessage(deCompoundMessage, nullptr);
if(!deCompoundFrame.isEmpty()){
frames.append(deCompoundFrame);
}
// Followed, by a standard OR compound directed message...
QString dirCompoundMessage = QString("<%1%2%3>").arg(dirTo).arg(dirCmd).arg(dirNum);
QString dirCompoundFrame = Varicode::packCompoundMessage(dirCompoundMessage, nullptr);
if(!dirCompoundFrame.isEmpty()){
frames.append(dirCompoundFrame);
}
shouldUseStandardFrame = false;
}
if(shouldUseStandardFrame) {
// otherwise, just send the standard directed frame
frames.append(frame);
}
line = line.mid(n);
// generate a checksum for buffered commands with line data
if(Varicode::isCommandBuffered(dirCmd) && !line.isEmpty()){
qDebug() << "generating checksum for line" << line << line.mid(1);
// strip leading whitespace after a buffered directed command
line = lstrip(line);
qDebug() << "before:" << line;
int checksumSize = Varicode::isCommandChecksumed(dirCmd);
if(checksumSize == 32){
line = line + " " + Varicode::checksum32(line);
} else if (checksumSize == 16) {
line = line + " " + Varicode::checksum16(line);
} else if (checksumSize == 0) {
// pass
}
qDebug() << "after:" << line;
}
#if 0
// APRS:
if(dirCmd.trimmed() == "APRS:" && !m_aprsClient->isPasscodeValid()){
MessageBox::warning_message(this, tr ("Please enter a valid APRS passcode in the settings to send an APRS packet."));
}
#endif
}
if(useDat){
frames.append(frame);
line = line.mid(m);
}
}
}
return frames;
}
BuildMessageFramesThread::BuildMessageFramesThread(const QString &mycall, const QString &basecall, const QString &mygrid, bool compound, const QString &selectedCall, const QString &text, QObject *parent):
QThread(parent),
m_mycall{mycall},
m_basecall{basecall},
m_mygrid{mygrid},
m_compound{compound},
m_selectedCall{selectedCall},
m_text{text}
{
}
void BuildMessageFramesThread::run(){
auto results = Varicode::buildMessageFrames(
m_mycall,
m_basecall,
m_mygrid,
m_compound,
m_selectedCall,
m_text
);
emit resultReady(results);
}

View File

@ -10,6 +10,7 @@
#include <QRegExp>
#include <QString>
#include <QVector>
#include <QThread>
class Varicode
{
@ -56,6 +57,9 @@ public:
//Varicode();
static QString rstrip(const QString& str);
static QString lstrip(const QString& str);
static QMap<QString, QString> defaultHuffTable();
static QMap<QString, QString> defaultHuffTableEscaped();
static QString cqString(int number);
@ -142,6 +146,40 @@ public:
static QString packDataMessage(QString const& text, int *n);
static QString unpackDataMessage(QString const& text, quint8 *pType);
static QStringList buildMessageFrames(
QString const& mycall,
QString const& basecall,
QString const& mygrid,
bool compound,
QString const& selectedCall,
QString const& text
);
};
class BuildMessageFramesThread : public QThread
{
Q_OBJECT
public:
BuildMessageFramesThread(QString const& mycall,
QString const& basecall,
QString const& mygrid,
bool compound,
QString const& selectedCall,
QString const& text,
QObject *parent=nullptr);
void run() override;
signals:
void resultReady(const QStringList s);
private:
QString m_mycall;
QString m_basecall;
QString m_mygrid;
bool m_compound;
QString m_selectedCall;
QString m_text;
};
#endif // VARICODE_H