diff --git a/mainwindow.cpp b/mainwindow.cpp index f5b41de..4bd2a43 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -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 - * -> then <....>: J1Y ACK - * -> then - * - * CASE 2: Compound To: KN4CRD: J1Y/P ACK - * -> One standard compound frame, followed by a compound directed frame - * -> then - * - * CASE 3: Compound From & To: KN4CRD/P: J1Y/P ACK - * -> One standard compound frame, followed by a compound directed frame - * -> then - **/ - 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 (ft8msgbits), - const_cast (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; diff --git a/mainwindow.h b/mainwindow.h index 8c336e3..8f34be8 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -95,6 +95,7 @@ class DecodedText; using namespace std; typedef std::function 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[], diff --git a/varicode.cpp b/varicode.cpp index 0240b3f..3670ad0 100644 --- a/varicode.cpp +++ b/varicode.cpp @@ -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 + * -> then <....>: J1Y ACK + * -> then + * + * CASE 2: Compound To: KN4CRD: J1Y/P ACK + * -> One standard compound frame, followed by a compound directed frame + * -> then + * + * CASE 3: Compound From & To: KN4CRD/P: J1Y/P ACK + * -> One standard compound frame, followed by a compound directed frame + * -> then + **/ + 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); +} diff --git a/varicode.h b/varicode.h index 8ad340f..fcd9712 100644 --- a/varicode.h +++ b/varicode.h @@ -10,6 +10,7 @@ #include #include #include +#include class Varicode { @@ -56,6 +57,9 @@ public: //Varicode(); + static QString rstrip(const QString& str); + static QString lstrip(const QString& str); + static QMap defaultHuffTable(); static QMap 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