Complete UI functionality

This commit is contained in:
Jordan Sherer 2018-07-05 04:45:55 -04:00
parent 9ed0fe80d2
commit 022866b52b
3 changed files with 283 additions and 106 deletions

View File

@ -163,8 +163,8 @@ QVector<QColor> 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 = "<strong>" + text + "</strong>";
// TODO: jsherer - move this out of this function
m_rxFrameBlockNumbers.clear();
}
if(found){
c.insertHtml(text);
} else {
c.insertHtml(QString("<strong>%1</strong> - %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<QTableWidgetItem*> 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<QTableWidgetItem*> 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<QString> 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)

View File

@ -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<QString> m_txFrameQueue;
QQueue<RXDetail> m_rxFrameQueue;
QMap<int, int> m_rxFrameBlockNumbers; // freq -> block
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;

View File

@ -742,6 +742,11 @@ background-color: yellow;
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
@ -825,6 +830,7 @@ background-color: yellow;
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
<italic>true</italic>
</font>
</property>
@ -834,6 +840,9 @@ background-color: yellow;
<property name="styleSheet">
<string notr="true">background-color:#ffeaa7;</string>
</property>
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
@ -848,6 +857,11 @@ background-color: yellow;
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="styleSheet">
<string notr="true">QTextEdit { background:rgb(255, 255, 255); }
@ -865,6 +879,11 @@ QTextEdit[readOnly=&quot;true&quot;] {
</widget>
</widget>
<widget class="QTableWidget" name="tableWidgetCalls">
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
@ -892,21 +911,11 @@ QTextEdit[readOnly=&quot;true&quot;] {
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<row>
<property name="text">
<string>0</string>
</property>
</row>
<column>
<property name="text">
<string>Callsign</string>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>allcall</string>
</property>
</item>
</widget>
</widget>
<widget class="QWidget" name="macroHorizonalWidget" native="true">
@ -941,32 +950,6 @@ QTextEdit[readOnly=&quot;true&quot;] {
<property name="bottomMargin">
<number>0</number>
</property>
<item row="1" column="1">
<widget class="QPushButton" name="qtcMacroButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>QTC</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="snrMacroButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>SNR</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="cqMacroButton">
<property name="minimumSize">
@ -983,7 +966,33 @@ QTextEdit[readOnly=&quot;true&quot;] {
</property>
</widget>
</item>
<item row="1" column="5">
<item row="1" column="1">
<widget class="QPushButton" name="replyMacroButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>REPLY</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="snrMacroButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>SNR</string>
</property>
</widget>
</item>
<item row="1" column="4">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@ -1000,6 +1009,32 @@ QTextEdit[readOnly=&quot;true&quot;] {
</spacer>
</item>
<item row="1" column="6">
<widget class="QPushButton" name="stopTxButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Halt</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="macrosMacroButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Macros</string>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QPushButton" name="startTxButton">
<property name="enabled">
<bool>false</bool>
@ -1023,45 +1058,6 @@ background-color: #00ff00;
</property>
</widget>
</item>
<item row="1" column="7">
<widget class="QPushButton" name="stopTxButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Halt</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="qthMacroButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>QTH</string>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QPushButton" name="macrosMacroButton">
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Macros</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QFrame" name="frame_5">
@ -3961,6 +3957,9 @@ list. The list can be maintained in Settings (F2).</string>
</property>
</action>
<action name="actionOpen">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Open</string>
</property>
@ -3969,6 +3968,9 @@ list. The list can be maintained in Settings (F2).</string>
</property>
</action>
<action name="actionOpen_next_in_directory">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Open next in directory</string>
</property>
@ -3977,6 +3979,9 @@ list. The list can be maintained in Settings (F2).</string>
</property>
</action>
<action name="actionDecode_remaining_files_in_directory">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Decode remaining files in directory</string>
</property>
@ -3985,6 +3990,9 @@ list. The list can be maintained in Settings (F2).</string>
</property>
</action>
<action name="actionDelete_all_wav_files_in_SaveDir">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Delete all *.wav &amp;&amp; *.c2 files in SaveDir</string>
</property>
@ -4496,6 +4504,9 @@ list. The list can be maintained in Settings (F2).</string>
</property>
</action>
<action name="actionErase_FoxQSO_txt">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Erase FoxQSO.txt</string>
</property>