Reorganized message transmission semantics

This commit is contained in:
Jordan Sherer 2018-07-02 22:54:26 -04:00
parent f610e946fc
commit c517b555d8
3 changed files with 346 additions and 66 deletions

View File

@ -162,8 +162,9 @@ QVector<QColor> g_ColorTbl;
namespace
{
Radio::Frequency constexpr default_frequency {14076000};
Radio::Frequency constexpr default_frequency {14074000};
QRegExp message_alphabet {"[- @A-Za-z0-9+./?#<>]*"};
QRegExp message_input_alphabet {"[- @A-Za-z0-9+./?#<>\n]*"};
// grid exact match excluding RR73
QRegularExpression grid_regexp {"\\A(?![Rr]{2}73)[A-Ra-r]{2}[0-9]{2}([A-Xa-x]{2}){0,1}\\z"};
@ -681,6 +682,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
connect (ui->extFreeTextMsg
, &QTextEdit::textChanged
, [this] () {on_extFreeTextMsg_currentTextChanged (ui->extFreeTextMsg->toPlainText ());});
connect (ui->extFreeTextMsgEdit
, &QTextEdit::textChanged
, [this] () {on_extFreeTextMsgEdit_currentTextChanged (ui->extFreeTextMsgEdit->toPlainText ());});
connect(&m_guiTimer, &QTimer::timeout, this, &MainWindow::guiUpdate);
m_guiTimer.start(100); //### Don't change the 100 ms! ###
@ -939,6 +943,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
}
//UI Customizations
m_wideGraph.data()->installEventFilter(new EscapeKeyPressEater());
ui->mdiArea->addSubWindow(m_wideGraph.data(), Qt::Dialog | Qt::FramelessWindowHint | Qt::CustomizeWindowHint | Qt::Tool)->showMaximized();
ui->menuDecode->setEnabled(false);
ui->menuMode->setEnabled(false);
@ -1757,6 +1762,11 @@ void MainWindow::on_autoButton_clicked (bool checked)
ui->sbTxPercent->setPalette(palette);
}
m_tAutoOn=QDateTime::currentMSecsSinceEpoch()/1000;
// stop tx, reset the ui and message queue
if(!checked){
on_stopTxButton_clicked();
}
}
void MainWindow::auto_tx_mode (bool state)
@ -3760,6 +3770,34 @@ void MainWindow::guiUpdate()
} //End of guiUpdate
void MainWindow::startTx()
{
if(!prepareNextMessageFrame()){
return;
}
m_ntx=9;
m_QSOProgress = CALLING;
set_dateTimeQSO(-1);
ui->rbNextFreeTextMsg->setChecked(true);
if (m_transmitting) m_restart=true;
// detect if we're currently in a possible transmit cycle...and if so, wait until the next one...
QDateTime now {QDateTime::currentDateTimeUtc()};
int s=now.time().second();
int n=s % (2*m_TRperiod);
if((n <= m_TRperiod && m_txFirst) || (n > m_TRperiod && !m_txFirst)){
ui->txFirstCheckBox->setChecked(!m_txFirst);
}
// hack the auto button to kick off the transmit
if(!ui->autoButton->isChecked()){
ui->autoButton->setEnabled(true);
ui->autoButton->click();
ui->autoButton->setEnabled(false);
}
}
void MainWindow::startTx2()
{
if (!m_modulator->isActive ()) { // TODO - not thread safe
@ -3787,6 +3825,11 @@ void MainWindow::startTx2()
}
}
void MainWindow::continueTx()
{
ui->txFirstCheckBox->setChecked(!m_txFirst);
}
void MainWindow::stopTx()
{
Q_EMIT endTransmitMessage ();
@ -3798,7 +3841,14 @@ void MainWindow::stopTx()
tx_status_label.setText("");
}
if(ui->tabWidget->currentIndex() == 3){
if(prepareNextMessageFrame()){
continueTx();
} else {
on_stopTxButton_clicked();
}
/*
if(true || ui->tabWidget->currentIndex() == 3){
//1. check to see if there are more messages to send
//2. if there are, fixup next message and continue transmitting
//3. if not, allow the transmission to stop
@ -3811,12 +3861,19 @@ void MainWindow::stopTx()
} else {
if(ui->autoButton->isChecked()){
ui->autoButton->click();
ui->autoButton->setEnabled(false);
}
if(ui->startTxButton->isChecked()){
ui->startTxButton->setChecked(false);
}
ui->nextFreeTextMsg->clear();
ui->extFreeTextMsg->clear();
ui->extFreeTextMsgEdit->clear();
ui->extFreeTextMsgEdit->setEnabled(true);
m_extFreeTxtPos = 0;
}
}
*/
ptt0Timer.start(200); //end-of-transmission sequencer delay
monitor (true);
@ -4042,35 +4099,6 @@ void MainWindow::on_txb6_clicked()
if (m_transmitting) m_restart=true;
}
void MainWindow::on_pbNextFreeTextMsg_clicked()
{
m_ntx=9;
m_QSOProgress = CALLING;
set_dateTimeQSO(-1);
ui->rbNextFreeTextMsg->setChecked(true);
if (m_transmitting) m_restart=true;
splitNextFreeTextMsg();
// TODO: detect if we're currently in a possible transmit cycle...and if so, wait...
QDateTime now {QDateTime::currentDateTimeUtc()};
int s=now.time().second();
int n=s % (2*m_TRperiod);
if((n <= m_TRperiod && m_txFirst) || (n > m_TRperiod && !m_txFirst)){
ui->txFirstCheckBox->setChecked(!m_txFirst);
}
if(!ui->autoButton->isChecked()){
ui->autoButton->click();
}
}
void MainWindow::on_rbNextFreeTextMsg_toggled (bool status)
{
if (status) {
m_ntx = 9;
}
}
void MainWindow::doubleClickOnCall2(Qt::KeyboardModifiers modifiers)
{
set_dateTimeQSO(-1); // reset our QSO start time
@ -4921,6 +4949,41 @@ void MainWindow::on_tx6_editingFinished() //tx6 edited
msgtype(t, ui->tx6);
}
void MainWindow::resetMessage(){
resetMessageUI();
resetMessageTransmitQueue();
}
void MainWindow::resetMessageUI(){
ui->nextFreeTextMsg->clear();
ui->extFreeTextMsg->clear();
ui->extFreeTextMsgEdit->clear();
if(ui->startTxButton->isChecked()){
ui->startTxButton->setChecked(false);
}
}
void MainWindow::createMessageTransmitQueue(QString const& text){
resetMessageTransmitQueue();
auto frames = buildFT8MessageFrames(text);
m_txFrameQueue.append(frames);
m_txFrameCount = frames.length();
}
void MainWindow::resetMessageTransmitQueue(){
m_txFrameCount = 0;
m_txFrameQueue.clear();
}
QString MainWindow::popMessageFrame(){
if(m_txFrameQueue.isEmpty()){
return QString();
}
return m_txFrameQueue.dequeue();
}
void MainWindow::on_nextFreeTextMsg_currentTextChanged (QString const& text)
{
msgtype(text, ui->nextFreeTextMsg);
@ -4928,6 +4991,7 @@ void MainWindow::on_nextFreeTextMsg_currentTextChanged (QString const& text)
void MainWindow::on_extFreeTextMsg_currentTextChanged (QString const& text)
{
/*
QString x;
QString::const_iterator i;
for(i = text.constBegin(); i != text.constEnd(); i++){
@ -4945,7 +5009,59 @@ void MainWindow::on_extFreeTextMsg_currentTextChanged (QString const& text)
}
int count = countFreeTextMsgs(x.trimmed().mid(m_extFreeTxtPos).trimmed());
ui->lblTxNum->setText(QString("Remaining Tx Sequences: %1").arg(count));
//ui->lblTxNum->setText(QString("Remaining Tx Sequences: %1").arg(count));
QString sendText = count > 0 ? QString("Send (%1)").arg(count) : "Send";
ui->startTxButton->setText(sendText);
*/
}
void MainWindow::on_extFreeTextMsgEdit_currentTextChanged (QString const& text)
{
QString x;
QString::const_iterator i;
for(i = text.constBegin(); i != text.constEnd(); i++){
if(message_input_alphabet.exactMatch(QString(*i))){
x += (*i).toUpper();
}
}
if(x != text){
int pos = ui->extFreeTextMsgEdit->textCursor().position();
int maxpos = x.size();
ui->extFreeTextMsgEdit->setPlainText(x);
QTextCursor c = ui->extFreeTextMsgEdit->textCursor();
c.setPosition(pos < maxpos ? pos : maxpos, QTextCursor::MoveAnchor);
ui->extFreeTextMsgEdit->setTextCursor(c);
}
int count = buildFT8MessageFrames(x).length();
if(count > 0){
ui->startTxButton->setText(QString("Send (%1)").arg(count));
ui->startTxButton->setEnabled(true);
} else {
ui->startTxButton->setText("Send");
ui->startTxButton->setEnabled(false);
}
}
QStringList MainWindow::buildFT8MessageFrames(QString const& text){
QStringList frames;
QString input = QString(text).replace("\n", " ").replace(" ", " ");
while(input.size() > 0){
QString frame = parseFT8Message(input);
if(frame.isEmpty()){
break;
}
frames.append(frame);
int sz = input.size();
input = input.remove(QRegExp("^" + QRegExp::escape(frame))).trimmed();
if(input.size() == sz){
break;
}
}
return frames;
}
QString MainWindow::parseFT8Message(QString input){
@ -4969,6 +5085,7 @@ QString MainWindow::parseFT8Message(QString input){
}
int MainWindow::countFreeTextMsgs(QString input){
/*
int count = 0;
while(input.size() > 0){
QString nextTxt = parseFT8Message(input);
@ -4981,10 +5098,22 @@ int MainWindow::countFreeTextMsgs(QString input){
}
}
return count;
*/
}
void MainWindow::splitNextFreeTextMsg()
bool MainWindow::prepareNextMessageFrame()
{
QString frame = popMessageFrame();
if(frame.isEmpty()){
ui->nextFreeTextMsg->clear();
return false;
} else {
ui->nextFreeTextMsg->setText(frame);
return true;
}
/*
QString txt = ui->extFreeTextMsg->toPlainText().trimmed().mid(m_extFreeTxtPos).trimmed();
QString nextTxt = parseFT8Message(txt);
@ -4992,6 +5121,7 @@ void MainWindow::splitNextFreeTextMsg()
QRegExp n = QRegExp("^" + QRegExp::escape(nextTxt));
ui->extFreeTextMsg->setPlainText(txt.remove(n).trimmed());
*/
/*
if(txt.contains(n)){
@ -5007,6 +5137,73 @@ void MainWindow::splitNextFreeTextMsg()
}
// this function is called by auto_tx_mode, which is called by autoButton.clicked
void MainWindow::on_startTxButton_toggled(bool checked)
{
if(checked){
createMessageTransmitQueue(ui->extFreeTextMsgEdit->toPlainText());
startTx();
} else {
resetMessage();
}
/*
if(ui->startTxButton->isChecked()){
ui->extFreeTextMsg->setPlainText(ui->extFreeTextMsgEdit->toPlainText());
ui->extFreeTextMsgEdit->clear();
on_pbExtFreeTextMsg_clicked();
} else {
ui->stopTxButton->click();
}
*/
/*
if(ui->startTxButton->isChecked()) {
ui->extFreeTextMsgEdit->setEnabled(false);
on_pbExtFreeTextMsg_clicked();
} else {
ui->extFreeTextMsgEdit->setEnabled(true);
ui->extFreeTextMsgEdit->clear();
on_stopTxButton_clicked();
}
*/
}
void MainWindow::splitAndSendNextMessage()
{
/*
m_ntx=9;
m_QSOProgress = CALLING;
set_dateTimeQSO(-1);
ui->rbNextFreeTextMsg->setChecked(true);
if (m_transmitting) m_restart=true;
splitNextFreeTextMsg();
// TODO: detect if we're currently in a possible transmit cycle...and if so, wait...
QDateTime now {QDateTime::currentDateTimeUtc()};
int s=now.time().second();
int n=s % (2*m_TRperiod);
if((n <= m_TRperiod && m_txFirst) || (n > m_TRperiod && !m_txFirst)){
ui->txFirstCheckBox->setChecked(!m_txFirst);
}
if(!ui->autoButton->isEnabled()){
ui->autoButton->setEnabled(true);
}
if(!ui->autoButton->isChecked()){
ui->autoButton->click();
ui->autoButton->setEnabled(false);
}
*/
}
void MainWindow::on_rbNextFreeTextMsg_toggled (bool status)
{
if (status) {
m_ntx = 9;
}
}
void MainWindow::on_dxCallEntry_textChanged (QString const& call)
{
m_hisCall = call;
@ -6091,6 +6288,8 @@ void MainWindow::on_stopTxButton_clicked() //Stop Tx
m_bCallingCQ = false;
m_bAutoReply = false; // ready for next
ui->cbFirst->setStyleSheet ("");
resetMessage();
}
void MainWindow::rigOpen ()
@ -6115,10 +6314,22 @@ void MainWindow::on_pbT2R_clicked()
}
}
static int roundUp(int numToRound, int multiple)
{
if(multiple == 0)
{
return numToRound;
}
int roundDown = ( (int) (numToRound) / multiple) * multiple;
return roundDown + multiple;
}
void MainWindow::on_beaconButton_clicked()
{
if(ui->beaconButton->isChecked()){
m_nextBeacon = QDateTime::currentDateTimeUtc().addSecs(300);
int timestamp = QDateTime::currentDateTimeUtc().addSecs(300).toSecsSinceEpoch();
m_nextBeacon = QDateTime::fromSecsSinceEpoch(roundUp(timestamp, 15) + 1, QTimeZone::utc());
}
}
@ -6902,6 +7113,7 @@ void MainWindow::postDecode (bool is_new, QString const& message)
ui->tableWidgetRXAll->setItem(ui->tableWidgetRXAll->rowCount() - 1, 2, new QTableWidgetItem(joined));
}
}
ui->tableWidgetRXAll->resizeColumnsToContents();
// TODO: keep track of selection
ui->listWidget->clear();

View File

@ -119,6 +119,11 @@ public slots:
void msgAvgDecode2();
void fastPick(int x0, int x1, int y);
void resetMessage();
void resetMessageUI();
void createMessageTransmitQueue(QString const& text);
void resetMessageTransmitQueue();
QString popMessageFrame();
protected:
void keyPressEvent (QKeyEvent *) override;
void closeEvent(QCloseEvent *) override;
@ -183,7 +188,8 @@ private slots:
void on_txb5_clicked();
void on_txb5_doubleClicked ();
void on_txb6_clicked();
void on_pbNextFreeTextMsg_clicked();
void on_startTxButton_toggled(bool checked);
void splitAndSendNextMessage();
void on_rbNextFreeTextMsg_toggled (bool status);
void on_lookupButton_clicked();
void on_addButton_clicked();
@ -206,8 +212,10 @@ private slots:
void on_actionErase_ALL_TXT_triggered();
void on_actionErase_FoxQSO_txt_triggered();
void on_actionErase_wsjtx_log_adi_triggered();
void startTx();
void startTx2();
void startP1();
void continueTx();
void stopTx();
void stopTx2();
void on_pbCallCQ_clicked();
@ -221,9 +229,11 @@ private slots:
void on_freeTextMsg_currentTextChanged (QString const&);
void on_nextFreeTextMsg_currentTextChanged (QString const&);
void on_extFreeTextMsg_currentTextChanged (QString const&);
void on_extFreeTextMsgEdit_currentTextChanged (QString const&);
QStringList buildFT8MessageFrames(QString const& text);
QString parseFT8Message(QString input);
int countFreeTextMsgs(QString input);
void splitNextFreeTextMsg();
bool prepareNextMessageFrame();
void on_rptSpinBox_valueChanged(int n);
void killFile();
void on_tuneButton_clicked (bool);
@ -611,6 +621,8 @@ private:
int snr;
};
int m_txFrameCount;
QQueue<QString> m_txFrameQueue;
QMap<int, QList<ActivityDetail>> m_bandActivity; // freq -> [(text, last timestamp), ...]
QMap<QString, CallDetail> m_callActivity; // call -> (last freq, last timestamp)
QMap<QString,FoxQSO> m_foxQSO;
@ -731,6 +743,23 @@ private:
void writeFoxQSO(QString msg);
};
class EscapeKeyPressEater : public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event){
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if(keyEvent->key() == Qt::Key_Escape){
return true;
}
}
// standard event processing
return QObject::eventFilter(obj, event);
}
};
extern int killbyname(const char* progName);
extern void getDev(int* numDevices,char hostAPI_DeviceName[][50],
int minChan[], int maxChan[],

View File

@ -266,6 +266,7 @@ o</string>
<string notr="true">QLabel {
font-family: MS Shell Dlg 2;
font-size: 14pt;
line-height:12pt;
color : white;
}</string>
</property>
@ -297,7 +298,7 @@ color : white;
<property name="styleSheet">
<string notr="true">QLabel {
font-family: MS Shell Dlg 2;
font-size: 12pt;
font-size: 11pt;
color : white;
}</string>
</property>
@ -507,7 +508,7 @@ background-color: #6699ff;
<item row="0" column="2">
<widget class="QPushButton" name="autoButton">
<property name="enabled">
<bool>false</bool>
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@ -737,10 +738,19 @@ background-color: yellow;
<enum>Qt::DotLine</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
<bool>false</bool>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>30</number>
</attribute>
<attribute name="horizontalHeaderMinimumSectionSize">
<number>20</number>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
@ -810,7 +820,12 @@ background-color: yellow;
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">QTextEdit { background:rgb(255, 255, 255); }</string>
<string notr="true">QTextEdit { background:rgb(255, 255, 255); }
QTextEdit[readOnly=&quot;true&quot;] {
background:#EEE;
font-style:italic;
}</string>
</property>
<property name="acceptRichText">
<bool>false</bool>
@ -888,8 +903,8 @@ background-color: yellow;
</property>
</widget>
</item>
<item row="1" column="6">
<widget class="QPushButton" name="stopTxButton">
<item row="1" column="3">
<widget class="QPushButton" name="snrMacroButton">
<property name="minimumSize">
<size>
<width>0</width>
@ -897,7 +912,7 @@ background-color: yellow;
</size>
</property>
<property name="text">
<string>Halt</string>
<string>SNR</string>
</property>
</widget>
</item>
@ -918,7 +933,47 @@ background-color: yellow;
</widget>
</item>
<item row="1" column="5">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="6">
<widget class="QPushButton" name="startTxButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QPushButton:checked {
background-color: #00ff00;
}</string>
</property>
<property name="text">
<string>Send</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="QPushButton" name="stopTxButton">
<property name="minimumSize">
<size>
<width>0</width>
@ -926,7 +981,7 @@ background-color: yellow;
</size>
</property>
<property name="text">
<string>Send</string>
<string>Halt</string>
</property>
</widget>
</item>
@ -944,23 +999,7 @@ background-color: yellow;
</widget>
</item>
<item row="1" column="4">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="snrMacroButton">
<widget class="QPushButton" name="macrosMacroButton">
<property name="minimumSize">
<size>
<width>0</width>
@ -968,7 +1007,7 @@ background-color: yellow;
</size>
</property>
<property name="text">
<string>SNR</string>
<string>Macros</string>
</property>
</widget>
</item>
@ -1944,7 +1983,7 @@ background-color: yellow;
<enum>QTabWidget::Triangular</enum>
</property>
<property name="currentIndex">
<number>0</number>
<number>3</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
@ -2831,7 +2870,7 @@ list. The list can be maintained in Settings (F2).</string>
<item>
<widget class="QLineEdit" name="nextFreeTextMsg">
<property name="maxLength">
<number>100</number>
<number>10000</number>
</property>
<property name="frame">
<bool>false</bool>
@ -2875,7 +2914,7 @@ list. The list can be maintained in Settings (F2).</string>
</widget>
</item>
<item>
<widget class="QPushButton" name="pbNextFreeTextMsg">
<widget class="QPushButton" name="pbNextFreeTextMsg_old">
<property name="text">
<string>Next</string>
</property>