From 022866b52b7d9fcbff3d6a7575a9c0182e8cc9f2 Mon Sep 17 00:00:00 2001 From: Jordan Sherer Date: Thu, 5 Jul 2018 04:45:55 -0400 Subject: [PATCH] Complete UI functionality --- mainwindow.cpp | 206 ++++++++++++++++++++++++++++++++++++++++++------- mainwindow.h | 20 ++++- mainwindow.ui | 163 ++++++++++++++++++++------------------ 3 files changed, 283 insertions(+), 106 deletions(-) diff --git a/mainwindow.cpp b/mainwindow.cpp index 994aaba..e7e8b06 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -163,8 +163,8 @@ QVector g_ColorTbl; namespace { Radio::Frequency constexpr default_frequency {14074000}; - QRegExp message_alphabet {"[- @A-Za-z0-9+./?#<>]*"}; - QRegExp message_input_alphabet {"[- @A-Za-z0-9+./?#<>\n]*"}; + 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"}; @@ -3007,6 +3007,15 @@ void MainWindow::readFromStdout() //readFromStdout } ActivityDetail d; + d.firstCall = decodedtext.CQersCall(); + if(d.firstCall.isEmpty()){ + auto words = decodedtext.messageWords(); + if(words.length() > 1){ + d.firstCall = words.at(0); + d.secondCall = words.at(1); + } + } + d.freq = offset; d.text = decodedtext.messageWords().first().trimmed(); d.timestamp = QDateTime::currentDateTimeUtc().toMSecsSinceEpoch(); @@ -3074,7 +3083,12 @@ void MainWindow::readFromStdout() //readFromStdout m_QSOText = decodedtext.string ().trimmed (); // TODO: jsherer - parse decode... - //ui->textEditRXAll->insertHtml(decodedtext.messageWords().first().trimmed() + "\n"); + //logRxTxMessageText(decodedtext.messageWords().first().trimmed(), false); + RXDetail d; + d.freq = audioFreq; + d.text = decodedtext.messageWords().first(); + d.timestamp = QDateTime::currentDateTimeUtc().toSecsSinceEpoch(); + m_rxFrameQueue.append(d); } if(m_mode=="FT8" and m_config.bHound()) { @@ -4963,6 +4977,58 @@ void MainWindow::on_tx6_editingFinished() //tx6 edited msgtype(t, ui->tx6); } +int MainWindow::logRxTxMessageText(QDateTime date, QString text, bool tx, int block){ + auto c = ui->textEditRX->textCursor(); + + bool found = false; + if(block != -1){ + QTextBlock b = c.document()->findBlockByNumber(block); + c.setPosition(b.position()); + c.movePosition(QTextCursor::EndOfBlock); + found = true; + } else { + c.insertBlock(); + } + + if(tx){ + text = "" + text + ""; + + // TODO: jsherer - move this out of this function + m_rxFrameBlockNumbers.clear(); + } + + if(found){ + c.insertHtml(text); + } else { + c.insertHtml(QString("%1 - %2").arg(date.time().toString()).arg(text)); + } + + return c.blockNumber(); // ui->textEditRX->document()->lineCount(); +} + +void MainWindow::addMessageText(QString text){ + // TODO: jsherer - check to make sure we're not transmitting currently + QTextCursor c = ui->extFreeTextMsgEdit->textCursor(); + if(c.hasSelection()){ + c.removeSelectedText(); + } + + int pos = c.position(); + c.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); + + bool isSpace = c.selectedText().isEmpty() || c.selectedText().at(0).isSpace(); + c.clearSelection(); + + c.setPosition(pos); + + if(!isSpace){ + c.insertText(" "); + } + + c.insertText(text); + ui->extFreeTextMsgEdit->setFocus(); +} + void MainWindow::resetMessage(){ resetMessageUI(); resetMessageTransmitQueue(); @@ -4981,6 +5047,7 @@ void MainWindow::resetMessageUI(){ void MainWindow::createMessage(QString const& text){ resetMessageTransmitQueue(); createMessageTransmitQueue(text); + logRxTxMessageText(QDateTime::currentDateTimeUtc(), text, true); } void MainWindow::createMessageTransmitQueue(QString const& text){ @@ -5060,23 +5127,6 @@ void MainWindow::on_extFreeTextMsgEdit_currentTextChanged (QString const& text) } } -void MainWindow::on_tableWidgetCalls_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected){ - /* - if(selected.isEmpty()){ - return; - } - QString selectedCall = ui->tableWidgetCalls->selectedItems().first()->text(); - int offset = m_callActivity[selectedCall].freq; - - QList items = ui->tableWidgetRXAll->findItems(QString("%1").arg(offset), Qt::MatchExactly); - if(items.isEmpty()){ - return; - } - - ui->tableWidgetRXAll->setItemSelected(items.first(), true); - */ -} - QStringList MainWindow::buildFT8MessageFrames(QString const& text){ QStringList frames; QString input = QString(text).replace("\n", " ").replace(" ", " "); @@ -6289,8 +6339,8 @@ void MainWindow::on_clearAction_triggered(QObject * sender){ for(int i = ui->tableWidgetCalls->rowCount(); i >= 0; i--){ ui->tableWidgetCalls->removeRow(i); } - ui->tableWidgetCalls->insertRow(ui->tableWidgetCalls->rowCount()); - ui->tableWidgetCalls->setItem(ui->tableWidgetCalls->rowCount() - 1, 0, new QTableWidgetItem("allcall")); + //ui->tableWidgetCalls->insertRow(ui->tableWidgetCalls->rowCount()); + //ui->tableWidgetCalls->setItem(ui->tableWidgetCalls->rowCount() - 1, 0, new QTableWidgetItem("allcall")); } if(sender == ui->extFreeTextMsgEdit){ @@ -6298,10 +6348,66 @@ void MainWindow::on_clearAction_triggered(QObject * sender){ } if(sender == ui->textEditRX){ + // TODO: jsherer - move these ui->textEditRX->clear(); + m_rxFrameBlockNumbers.clear(); + m_rxFrameQueue.clear(); } } +void MainWindow::on_cqMacroButton_clicked(){ + QString text = QString("CQ %1 %2").arg(m_config.my_callsign()).arg(m_config.my_grid().left(4)); + addMessageText(text); +} + +void MainWindow::on_replyMacroButton_clicked(){ + auto items = ui->tableWidgetCalls->selectedItems(); + if(!items.isEmpty()){ + QString selectedCall = items.first()->text(); + addMessageText(selectedCall); + return; + } + + int offset = ui->RxFreqSpinBox->value(); + if(m_bandActivity.contains(offset)){ + auto activity = m_bandActivity[offset].last(); + if(!activity.firstCall.isEmpty()){ + addMessageText(activity.firstCall); + return; + } + } +} + +void MainWindow::on_snrMacroButton_clicked(){ + auto items = ui->tableWidgetCalls->selectedItems(); + if(!items.isEmpty()){ + QString selectedCall = items.first()->text(); + int snr = m_callActivity[selectedCall].snr; + QString text = QString("%1").arg(snr); + addMessageText(text); + return; + } + + int offset = ui->RxFreqSpinBox->value(); + if(m_bandActivity.contains(offset)){ + int snr = m_bandActivity[offset].last().snr; + QString text = QString("%1").arg(snr); + addMessageText(text); + return; + } +} + +void MainWindow::on_macrosMacroButton_clicked(){ + QMenu *menu = new QMenu(ui->macrosMacroButton); + foreach(QString macro, m_config.macros()->stringList()){ + QAction *action = menu->addAction(macro); + connect(action, &QAction::triggered, this, [this, macro](){ addMessageText(macro); }); + } + ui->macrosMacroButton->setMenu(menu); + ui->macrosMacroButton->showMenu(); +} + + void MainWindow::on_tableWidgetRXAll_cellClicked(int row, int col){ auto item = ui->tableWidgetRXAll->item(row, 0); int offset = item->text().toInt(); @@ -6320,12 +6426,22 @@ void MainWindow::on_tableWidgetRXAll_cellDoubleClicked(int row, int col){ int offset = item->text().toInt(); foreach(auto d, m_callActivity.values()){ if(d.freq == offset){ - ui->extFreeTextMsgEdit->append(d.call); + addMessageText(d.call); break; } } } +void MainWindow::on_tableWidgetRXAll_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected){ + if(ui->tableWidgetRXAll->selectedItems().isEmpty() && ui->tableWidgetCalls->selectedItems().isEmpty()){ + ui->replyMacroButton->setDisabled(true); + ui->snrMacroButton->setDisabled(true); + } else { + ui->replyMacroButton->setDisabled(false); + ui->snrMacroButton->setDisabled(false); + } +} + void MainWindow::on_tableWidgetCalls_cellClicked(int row, int col){ auto item = ui->tableWidgetCalls->item(row, 0); auto call = item->text(); @@ -6345,7 +6461,27 @@ void MainWindow::on_tableWidgetCalls_cellDoubleClicked(int row, int col){ auto item = ui->tableWidgetCalls->item(row, 0); auto call = item->text(); - ui->extFreeTextMsgEdit->append(call); + addMessageText(call); +} + + +void MainWindow::on_tableWidgetCalls_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected){ + on_tableWidgetRXAll_selectionChanged(selected, deselected); + + /* + if(selected.isEmpty()){ + return; + } + QString selectedCall = ui->tableWidgetCalls->selectedItems().first()->text(); + int offset = m_callActivity[selectedCall].freq; + + QList items = ui->tableWidgetRXAll->findItems(QString("%1").arg(offset), Qt::MatchExactly); + if(items.isEmpty()){ + return; + } + + ui->tableWidgetRXAll->setItemSelected(items.first(), true); + */ } void MainWindow::on_freeTextMsg_currentTextChanged (QString const& text) @@ -7212,7 +7348,7 @@ void MainWindow::postDecode (bool is_new, QString const& message) - // TODO: keep track of selection + // TODO: jsherer - keep track of selection int selectedOffset = -1; auto selectedItems = ui->tableWidgetRXAll->selectedItems(); if(!selectedItems.isEmpty()){ @@ -7284,7 +7420,7 @@ void MainWindow::postDecode (bool is_new, QString const& message) } ui->tableWidgetRXAll->resizeColumnsToContents(); - // TODO: keep track of selection + // TODO: jsherer - keep track of selection QString selectedCall; auto selectedCalls = ui->tableWidgetCalls->selectedItems(); if(!selectedCalls.isEmpty()){ @@ -7294,8 +7430,8 @@ void MainWindow::postDecode (bool is_new, QString const& message) ui->tableWidgetCalls->removeRow(i); } - ui->tableWidgetCalls->insertRow(ui->tableWidgetCalls->rowCount()); - ui->tableWidgetCalls->setItem(ui->tableWidgetCalls->rowCount() - 1, 0, new QTableWidgetItem("allcall")); + //ui->tableWidgetCalls->insertRow(ui->tableWidgetCalls->rowCount()); + //ui->tableWidgetCalls->setItem(ui->tableWidgetCalls->rowCount() - 1, 0, new QTableWidgetItem("allcall")); QList calls = m_callActivity.keys(); qSort(calls.begin(), calls.end()); @@ -7303,12 +7439,24 @@ void MainWindow::postDecode (bool is_new, QString const& message) CallDetail d = m_callActivity[call]; ui->tableWidgetCalls->insertRow(ui->tableWidgetCalls->rowCount()); ui->tableWidgetCalls->setItem(ui->tableWidgetCalls->rowCount() - 1, 0, new QTableWidgetItem(call)); - ui->tableWidgetCalls->setItem(ui->tableWidgetCalls->rowCount() - 1, 1, new QTableWidgetItem(d.grid)); + //ui->tableWidgetCalls->setItem(ui->tableWidgetCalls->rowCount() - 1, 1, new QTableWidgetItem(d.grid)); + if(call == selectedCall){ ui->tableWidgetCalls->selectRow(ui->tableWidgetCalls->rowCount() - 1); } } + // RX Activity + while(!m_rxFrameQueue.isEmpty()){ + RXDetail d = m_rxFrameQueue.first(); + m_rxFrameQueue.removeFirst(); + + auto date = QDateTime::fromSecsSinceEpoch(d.timestamp).toUTC(); + int freq = d.freq/10*10; + int block = m_rxFrameBlockNumbers.contains(freq) ? m_rxFrameBlockNumbers[freq] : -1; + block = logRxTxMessageText(date, d.text, false, block=block); + m_rxFrameBlockNumbers[freq] = block; + } } void MainWindow::postWSPRDecode (bool is_new, QStringList parts) diff --git a/mainwindow.h b/mainwindow.h index 80870de..5b6a791 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -119,6 +119,8 @@ public slots: void msgAvgDecode2(); void fastPick(int x0, int x1, int y); + int logRxTxMessageText(QDateTime date, QString text, bool tx, int block=-1); + void addMessageText(QString text); void resetMessage(); void resetMessageUI(); void createMessage(QString const& text); @@ -189,7 +191,6 @@ private slots: void on_txb5_clicked(); void on_txb5_doubleClicked (); void on_txb6_clicked(); - void on_tableWidgetCalls_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void on_startTxButton_toggled(bool checked); void splitAndSendNextMessage(); void on_rbNextFreeTextMsg_toggled (bool status); @@ -229,10 +230,16 @@ private slots: void on_rbGenMsg_clicked(bool checked); void on_rbFreeText_clicked(bool checked); void on_clearAction_triggered(QObject * sender); + void on_cqMacroButton_clicked(); + void on_replyMacroButton_clicked(); + void on_snrMacroButton_clicked(); + void on_macrosMacroButton_clicked(); void on_tableWidgetRXAll_cellClicked(int row, int col); void on_tableWidgetRXAll_cellDoubleClicked(int row, int col); + void on_tableWidgetRXAll_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void on_tableWidgetCalls_cellClicked(int row, int col); void on_tableWidgetCalls_cellDoubleClicked(int row, int col); + void on_tableWidgetCalls_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); void on_freeTextMsg_currentTextChanged (QString const&); void on_nextFreeTextMsg_currentTextChanged (QString const&); void on_extFreeTextMsg_currentTextChanged (QString const&); @@ -626,14 +633,25 @@ private: struct ActivityDetail { + QString firstCall; + QString secondCall; int freq; QString text; int timestamp; int snr; }; + struct RXDetail + { + int freq; + QString text; + int timestamp; + }; + int m_txFrameCount; QQueue m_txFrameQueue; + QQueue m_rxFrameQueue; + QMap m_rxFrameBlockNumbers; // freq -> block QMap> m_bandActivity; // freq -> [(text, last timestamp), ...] QMap m_callActivity; // call -> (last freq, last timestamp) QMap m_foxQSO; diff --git a/mainwindow.ui b/mainwindow.ui index 0a22c1f..122fe75 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -742,6 +742,11 @@ background-color: yellow; 0 + + + 12 + + QAbstractScrollArea::AdjustToContents @@ -825,6 +830,7 @@ background-color: yellow; + 12 true @@ -834,6 +840,9 @@ background-color: yellow; background-color:#ffeaa7; + + false + true @@ -848,6 +857,11 @@ background-color: yellow; 1 + + + 12 + + QTextEdit { background:rgb(255, 255, 255); } @@ -865,6 +879,11 @@ QTextEdit[readOnly="true"] { + + + 12 + + QAbstractItemView::NoEditTriggers @@ -892,21 +911,11 @@ QTextEdit[readOnly="true"] { false - - - 0 - - Callsign - - - allcall - - @@ -941,32 +950,6 @@ QTextEdit[readOnly="true"] { 0 - - - - - 0 - 30 - - - - QTC - - - - - - - - 0 - 30 - - - - SNR - - - @@ -983,7 +966,33 @@ QTextEdit[readOnly="true"] { - + + + + + 0 + 30 + + + + REPLY + + + + + + + + 0 + 30 + + + + SNR + + + + Qt::Horizontal @@ -1000,6 +1009,32 @@ QTextEdit[readOnly="true"] { + + + + 0 + 30 + + + + Halt + + + + + + + + 0 + 30 + + + + Macros + + + + false @@ -1023,45 +1058,6 @@ background-color: #00ff00; - - - - - 0 - 30 - - - - Halt - - - - - - - - 0 - 30 - - - - QTH - - - - - - - - 0 - 30 - - - - Macros - - - @@ -3961,6 +3957,9 @@ list. The list can be maintained in Settings (F2). + + false + Open @@ -3969,6 +3968,9 @@ list. The list can be maintained in Settings (F2). + + false + Open next in directory @@ -3977,6 +3979,9 @@ list. The list can be maintained in Settings (F2). + + false + Decode remaining files in directory @@ -3985,6 +3990,9 @@ list. The list can be maintained in Settings (F2). + + false + Delete all *.wav && *.c2 files in SaveDir @@ -4496,6 +4504,9 @@ list. The list can be maintained in Settings (F2). + + false + Erase FoxQSO.txt