mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-26 22:28:41 -05:00
Add WSPR decodes to UDP message protocol
The message_aggregator (MessageAggregator.cpp) has been updated to do something with WSPR decodes. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6101 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
79310954f4
commit
8b3ccfa3b6
@ -184,17 +184,148 @@ private:
|
||||
QFont text_font_;
|
||||
};
|
||||
|
||||
//
|
||||
// Beacons Model - simple data model for all beacon spots
|
||||
//
|
||||
// The model is a basic table with uniform row format. Rows consist of
|
||||
// QStandardItem instances containing the string representation of the
|
||||
// column data and if the underlying field is not a string then the
|
||||
// UserRole+1 role contains the underlying data item.
|
||||
//
|
||||
// Two slots are provided to add a new decode and remove all spots for
|
||||
// a client.
|
||||
//
|
||||
class BeaconsModel
|
||||
: public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
BeaconsModel (QObject * parent = nullptr)
|
||||
: QStandardItemModel {0, 9, parent}
|
||||
, text_font_ {"Courier", 10}
|
||||
{
|
||||
setHeaderData (0, Qt::Horizontal, tr ("Client"));
|
||||
setHeaderData (1, Qt::Horizontal, tr ("Time"));
|
||||
setHeaderData (2, Qt::Horizontal, tr ("Snr"));
|
||||
setHeaderData (3, Qt::Horizontal, tr ("DT"));
|
||||
setHeaderData (4, Qt::Horizontal, tr ("Frequency"));
|
||||
setHeaderData (5, Qt::Horizontal, tr ("Drift"));
|
||||
setHeaderData (6, Qt::Horizontal, tr ("Callsign"));
|
||||
setHeaderData (7, Qt::Horizontal, tr ("Grid"));
|
||||
setHeaderData (8, Qt::Horizontal, tr ("Power"));
|
||||
}
|
||||
|
||||
Q_SLOT void add_beacon_spot (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time
|
||||
, Frequency frequency, qint32 drift, QString const& callsign, QString const& grid
|
||||
, qint32 power)
|
||||
{
|
||||
if (!is_new)
|
||||
{
|
||||
int target_row {-1};
|
||||
for (auto row = 0; row < rowCount (); ++row)
|
||||
{
|
||||
if (data (index (row, 0)).toString () == client_id)
|
||||
{
|
||||
auto row_time = item (row, 1)->data ().toTime ();
|
||||
if (row_time == time
|
||||
&& item (row, 2)->data ().toInt () == snr
|
||||
&& item (row, 3)->data ().toFloat () == delta_time
|
||||
&& item (row, 4)->data ().value<Frequency> () == frequency
|
||||
&& data (index (row, 5)).toInt () == drift
|
||||
&& data (index (row, 6)).toString () == callsign
|
||||
&& data (index (row, 7)).toString () == grid
|
||||
&& data (index (row, 8)).toInt () == power)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (time <= row_time)
|
||||
{
|
||||
target_row = row; // last row with same time
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target_row >= 0)
|
||||
{
|
||||
insertRow (target_row + 1, make_row (client_id, time, snr, delta_time, frequency, drift, callsign, grid, power));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
appendRow (make_row (client_id, time, snr, delta_time, frequency, drift, callsign, grid, power));
|
||||
}
|
||||
|
||||
QList<QStandardItem *> make_row (QString const& client_id, QTime time, qint32 snr, float delta_time
|
||||
, Frequency frequency, qint32 drift, QString const& callsign
|
||||
, QString const& grid, qint32 power) const
|
||||
{
|
||||
auto time_item = new QStandardItem {time.toString ("hh:mm")};
|
||||
time_item->setData (time);
|
||||
time_item->setTextAlignment (Qt::AlignRight);
|
||||
|
||||
auto snr_item = new QStandardItem {QString::number (snr)};
|
||||
snr_item->setData (snr);
|
||||
snr_item->setTextAlignment (Qt::AlignRight);
|
||||
|
||||
auto dt = new QStandardItem {QString::number (delta_time)};
|
||||
dt->setData (delta_time);
|
||||
dt->setTextAlignment (Qt::AlignRight);
|
||||
|
||||
auto freq = new QStandardItem {Radio::pretty_frequency_MHz_string (frequency)};
|
||||
freq->setData (frequency);
|
||||
freq->setTextAlignment (Qt::AlignRight);
|
||||
|
||||
auto dri = new QStandardItem {QString::number (drift)};
|
||||
dri->setData (drift);
|
||||
dri->setTextAlignment (Qt::AlignRight);
|
||||
|
||||
auto gd = new QStandardItem {grid};
|
||||
gd->setTextAlignment (Qt::AlignRight);
|
||||
|
||||
auto pwr = new QStandardItem {QString::number (power)};
|
||||
pwr->setData (power);
|
||||
pwr->setTextAlignment (Qt::AlignRight);
|
||||
|
||||
QList<QStandardItem *> row {
|
||||
new QStandardItem {client_id}, time_item, snr_item, dt, freq, dri, new QStandardItem {callsign}, gd, pwr};
|
||||
Q_FOREACH (auto& item, row)
|
||||
{
|
||||
item->setEditable (false);
|
||||
item->setFont (text_font_);
|
||||
item->setTextAlignment (item->textAlignment () | Qt::AlignVCenter);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
Q_SLOT void clear_decodes (QString const& client_id)
|
||||
{
|
||||
for (auto row = rowCount () - 1; row >= 0; --row)
|
||||
{
|
||||
if (data (index (row, 0)).toString () == client_id)
|
||||
{
|
||||
removeRow (row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
QFont text_font_;
|
||||
};
|
||||
|
||||
class ClientWidget
|
||||
: public QDockWidget
|
||||
{
|
||||
Q_OBJECT;
|
||||
|
||||
public:
|
||||
explicit ClientWidget (QAbstractItemModel * decodes_model, QString const& id, QWidget * parent = 0)
|
||||
explicit ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model
|
||||
, QString const& id, QWidget * parent = 0)
|
||||
: QDockWidget {id, parent}
|
||||
, id_ {id}
|
||||
, decodes_table_view_ {new QTableView}
|
||||
, beacons_table_view_ {new QTableView}
|
||||
, message_line_edit_ {new QLineEdit}
|
||||
, decodes_stack_ {new QStackedLayout}
|
||||
, auto_off_button_ {new QPushButton {tr ("&Auto Off")}}
|
||||
, halt_tx_button_ {new QPushButton {tr ("&Halt Tx")}}
|
||||
, mode_label_ {new QLabel}
|
||||
@ -202,19 +333,14 @@ public:
|
||||
, frequency_label_ {new QLabel}
|
||||
, report_label_ {new QLabel}
|
||||
{
|
||||
auto content_layout = new QVBoxLayout;
|
||||
content_layout->setContentsMargins (QMargins {2, 2, 2, 2});
|
||||
|
||||
// set up table
|
||||
auto proxy_model = new DecodesFilterModel {id, this};
|
||||
proxy_model->setSourceModel (decodes_model);
|
||||
decodes_table_view_->setModel (proxy_model);
|
||||
// set up widgets
|
||||
auto decodes_proxy_model = new IdFilterModel {id, this};
|
||||
decodes_proxy_model->setSourceModel (decodes_model);
|
||||
decodes_table_view_->setModel (decodes_proxy_model);
|
||||
decodes_table_view_->verticalHeader ()->hide ();
|
||||
decodes_table_view_->hideColumn (0);
|
||||
content_layout->addWidget (decodes_table_view_);
|
||||
decodes_table_view_->horizontalHeader ()->setStretchLastSection (true);
|
||||
|
||||
// set up controls
|
||||
auto control_layout = new QHBoxLayout;
|
||||
auto form_layout = new QFormLayout;
|
||||
form_layout->addRow (tr ("Free text:"), message_line_edit_);
|
||||
message_line_edit_->setValidator (new QRegExpValidator {message_alphabet, this});
|
||||
@ -224,16 +350,44 @@ public:
|
||||
connect (message_line_edit_, &QLineEdit::editingFinished, [this] () {
|
||||
Q_EMIT do_free_text (id_, message_line_edit_->text (), true);
|
||||
});
|
||||
control_layout->addLayout (form_layout);
|
||||
control_layout->addWidget (auto_off_button_);
|
||||
control_layout->addWidget (halt_tx_button_);
|
||||
|
||||
auto decodes_page = new QWidget;
|
||||
auto decodes_layout = new QVBoxLayout {decodes_page};
|
||||
decodes_layout->setContentsMargins (QMargins {2, 2, 2, 2});
|
||||
decodes_layout->addWidget (decodes_table_view_);
|
||||
decodes_layout->addLayout (form_layout);
|
||||
|
||||
auto beacons_proxy_model = new IdFilterModel {id, this};
|
||||
beacons_proxy_model->setSourceModel (beacons_model);
|
||||
beacons_table_view_->setModel (beacons_proxy_model);
|
||||
beacons_table_view_->verticalHeader ()->hide ();
|
||||
beacons_table_view_->hideColumn (0);
|
||||
beacons_table_view_->horizontalHeader ()->setStretchLastSection (true);
|
||||
|
||||
auto beacons_page = new QWidget;
|
||||
auto beacons_layout = new QVBoxLayout {beacons_page};
|
||||
beacons_layout->setContentsMargins (QMargins {2, 2, 2, 2});
|
||||
beacons_layout->addWidget (beacons_table_view_);
|
||||
|
||||
decodes_stack_->addWidget (decodes_page);
|
||||
decodes_stack_->addWidget (beacons_page);
|
||||
|
||||
// stack alternative views
|
||||
auto content_layout = new QVBoxLayout;
|
||||
content_layout->setContentsMargins (QMargins {2, 2, 2, 2});
|
||||
content_layout->addLayout (decodes_stack_);
|
||||
|
||||
// set up controls
|
||||
auto control_button_box = new QDialogButtonBox;
|
||||
control_button_box->addButton (auto_off_button_, QDialogButtonBox::ActionRole);
|
||||
control_button_box->addButton (halt_tx_button_, QDialogButtonBox::ActionRole);
|
||||
connect (auto_off_button_, &QAbstractButton::clicked, [this] (bool /* checked */) {
|
||||
Q_EMIT do_halt_tx (id_, true);
|
||||
});
|
||||
connect (halt_tx_button_, &QAbstractButton::clicked, [this] (bool /* checked */) {
|
||||
Q_EMIT do_halt_tx (id_, false);
|
||||
});
|
||||
content_layout->addLayout (control_layout);
|
||||
content_layout->addWidget (control_button_box);
|
||||
|
||||
// set up status area
|
||||
auto status_bar = new QStatusBar;
|
||||
@ -254,8 +408,8 @@ public:
|
||||
setAllowedAreas (Qt::BottomDockWidgetArea);
|
||||
|
||||
// connect up table view signals
|
||||
connect (decodes_table_view_, &QTableView::doubleClicked, this, [this, proxy_model] (QModelIndex const& index) {
|
||||
Q_EMIT do_reply (proxy_model->mapToSource (index));
|
||||
connect (decodes_table_view_, &QTableView::doubleClicked, this, [this, decodes_proxy_model] (QModelIndex const& index) {
|
||||
Q_EMIT do_reply (decodes_proxy_model->mapToSource (index));
|
||||
});
|
||||
}
|
||||
|
||||
@ -265,7 +419,9 @@ public:
|
||||
{
|
||||
if (id == id_)
|
||||
{
|
||||
mode_label_->setText (QString {"Mode: %1%2"}.arg (mode).arg (tx_mode.isEmpty () ? tx_mode : '(' + tx_mode + ')'));
|
||||
mode_label_->setText (QString {"Mode: %1%2"}
|
||||
.arg (mode)
|
||||
.arg (tx_mode.isEmpty () || tx_mode == mode ? "" : '(' + tx_mode + ')'));
|
||||
dx_call_label_->setText ("DX CALL: " + dx_call);
|
||||
frequency_label_->setText ("QRG: " + Radio::pretty_frequency_MHz_string (f));
|
||||
report_label_->setText ("SNR: " + report);
|
||||
@ -277,27 +433,39 @@ public:
|
||||
}
|
||||
|
||||
Q_SLOT void decode_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/
|
||||
, float /*delta_time*/, quint32 /*delta_frequency*/, QString const& /*mode*/
|
||||
, QString const& /*message*/)
|
||||
, float /*delta_time*/, quint32 /*delta_frequency*/, QString const& /*mode*/
|
||||
, QString const& /*message*/)
|
||||
{
|
||||
if (client_id == id_)
|
||||
{
|
||||
decodes_stack_->setCurrentIndex (0);
|
||||
decodes_table_view_->resizeColumnsToContents ();
|
||||
decodes_table_view_->horizontalHeader ()->setStretchLastSection (true);
|
||||
decodes_table_view_->scrollToBottom ();
|
||||
}
|
||||
}
|
||||
|
||||
Q_SLOT void beacon_spot_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/
|
||||
, float /*delta_time*/, Frequency /*delta_frequency*/, qint32 /*drift*/, QString const& /*callsign*/
|
||||
, QString const& /*grid*/, qint32 /*power*/)
|
||||
{
|
||||
if (client_id == id_)
|
||||
{
|
||||
decodes_stack_->setCurrentIndex (1);
|
||||
beacons_table_view_->resizeColumnsToContents ();
|
||||
beacons_table_view_->scrollToBottom ();
|
||||
}
|
||||
}
|
||||
|
||||
Q_SIGNAL void do_reply (QModelIndex const&);
|
||||
Q_SIGNAL void do_halt_tx (QString const& id, bool auto_only);
|
||||
Q_SIGNAL void do_free_text (QString const& id, QString const& text, bool);
|
||||
|
||||
private:
|
||||
class DecodesFilterModel final
|
||||
class IdFilterModel final
|
||||
: public QSortFilterProxyModel
|
||||
{
|
||||
public:
|
||||
DecodesFilterModel (QString const& id, QObject * parent = nullptr)
|
||||
IdFilterModel (QString const& id, QObject * parent = nullptr)
|
||||
: QSortFilterProxyModel {parent}
|
||||
, id_ {id}
|
||||
{}
|
||||
@ -315,7 +483,9 @@ private:
|
||||
|
||||
QString id_;
|
||||
QTableView * decodes_table_view_;
|
||||
QTableView * beacons_table_view_;
|
||||
QLineEdit * message_line_edit_;
|
||||
QStackedLayout * decodes_stack_;
|
||||
QAbstractButton * auto_off_button_;
|
||||
QAbstractButton * halt_tx_button_;
|
||||
QLabel * mode_label_;
|
||||
@ -333,6 +503,7 @@ public:
|
||||
MainWindow ()
|
||||
: log_ {new QStandardItemModel {0, 10, this}}
|
||||
, decodes_model_ {new DecodesModel {this}}
|
||||
, beacons_model_ {new BeaconsModel {this}}
|
||||
, server_ {new MessageServer {this}}
|
||||
, multicast_group_line_edit_ {new QLineEdit}
|
||||
, log_table_view_ {new QTableView}
|
||||
@ -395,8 +566,11 @@ public:
|
||||
connect (server_, &MessageServer::client_opened, this, &MainWindow::add_client);
|
||||
connect (server_, &MessageServer::client_closed, this, &MainWindow::remove_client);
|
||||
connect (server_, &MessageServer::client_closed, decodes_model_, &DecodesModel::clear_decodes);
|
||||
connect (server_, &MessageServer::client_closed, beacons_model_, &BeaconsModel::clear_decodes);
|
||||
connect (server_, &MessageServer::decode, decodes_model_, &DecodesModel::add_decode);
|
||||
connect (server_, &MessageServer::WSPR_decode, beacons_model_, &BeaconsModel::add_beacon_spot);
|
||||
connect (server_, &MessageServer::clear_decodes, decodes_model_, &DecodesModel::clear_decodes);
|
||||
connect (server_, &MessageServer::clear_decodes, beacons_model_, &BeaconsModel::clear_decodes);
|
||||
connect (decodes_model_, &DecodesModel::reply, server_, &MessageServer::reply);
|
||||
|
||||
// UI behaviour
|
||||
@ -435,7 +609,7 @@ public:
|
||||
private:
|
||||
void add_client (QString const& id)
|
||||
{
|
||||
auto dock = new ClientWidget {decodes_model_, id, this};
|
||||
auto dock = new ClientWidget {decodes_model_, beacons_model_, id, this};
|
||||
dock->setAttribute (Qt::WA_DeleteOnClose);
|
||||
auto view_action = dock->toggleViewAction ();
|
||||
view_action->setEnabled (true);
|
||||
@ -443,6 +617,7 @@ private:
|
||||
addDockWidget (Qt::BottomDockWidgetArea, dock);
|
||||
connect (server_, &MessageServer::status_update, dock, &ClientWidget::update_status);
|
||||
connect (server_, &MessageServer::decode, dock, &ClientWidget::decode_added);
|
||||
connect (server_, &MessageServer::WSPR_decode, dock, &ClientWidget::beacon_spot_added);
|
||||
connect (dock, &ClientWidget::do_reply, decodes_model_, &DecodesModel::do_reply);
|
||||
connect (dock, &ClientWidget::do_halt_tx, server_, &MessageServer::halt_tx);
|
||||
connect (dock, &ClientWidget::do_free_text, server_, &MessageServer::free_text);
|
||||
@ -464,6 +639,7 @@ private:
|
||||
QStandardItemModel * log_;
|
||||
QMenu * view_menu_;
|
||||
DecodesModel * decodes_model_;
|
||||
BeaconsModel * beacons_model_;
|
||||
MessageServer * server_;
|
||||
QLineEdit * multicast_group_line_edit_;
|
||||
QTableView * log_table_view_;
|
||||
|
@ -272,9 +272,16 @@ MessageClient::MessageClient (QString const& id, QString const& server, port_typ
|
||||
, m_ {id, server_port, this}
|
||||
{
|
||||
connect (&*m_, static_cast<void (impl::*) (impl::SocketError)> (&impl::error)
|
||||
, [this] (impl::SocketError /* e */)
|
||||
, [this] (impl::SocketError e)
|
||||
{
|
||||
Q_EMIT error (m_->errorString ());
|
||||
#if defined (Q_OS_WIN) && QT_VERSION >= 0x050500
|
||||
if (e != impl::NetworkError) // take this out when Qt 5.5
|
||||
// stops doing this
|
||||
// spuriously
|
||||
#endif
|
||||
{
|
||||
Q_EMIT error (m_->errorString ());
|
||||
}
|
||||
});
|
||||
set_server (server);
|
||||
}
|
||||
@ -340,6 +347,19 @@ void MessageClient::decode (bool is_new, QTime time, qint32 snr, float delta_tim
|
||||
}
|
||||
}
|
||||
|
||||
void MessageClient::WSPR_decode (bool is_new, QTime time, qint32 snr, float delta_time, Frequency frequency
|
||||
, qint32 drift, QString const& callsign, QString const& grid, qint32 power)
|
||||
{
|
||||
if (m_->server_port_ && !m_->server_string_.isEmpty ())
|
||||
{
|
||||
QByteArray message;
|
||||
NetworkMessage::Builder out {&message, NetworkMessage::WSPRDecode, m_->id_, m_->schema_};
|
||||
out << is_new << time << snr << delta_time << frequency << drift << callsign.toUtf8 ()
|
||||
<< grid.toUtf8 () << power;
|
||||
m_->send_message (out, message);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageClient::clear_decodes ()
|
||||
{
|
||||
if (m_->server_port_ && !m_->server_string_.isEmpty ())
|
||||
|
@ -14,8 +14,8 @@ class QHostAddress;
|
||||
|
||||
//
|
||||
// MessageClient - Manage messages sent and replies received from a
|
||||
// matching server (MessageServer) at the other end of
|
||||
// the wire
|
||||
// matching server (MessageServer) at the other end of
|
||||
// the wire
|
||||
//
|
||||
//
|
||||
// Each outgoing message type is a Qt slot
|
||||
@ -50,6 +50,8 @@ public:
|
||||
, QString const& tx_mode, bool tx_enabled, bool transmitting, bool decoding);
|
||||
Q_SLOT void decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
|
||||
, QString const& mode, QString const& message);
|
||||
Q_SLOT void WSPR_decode (bool is_new, QTime time, qint32 snr, float delta_time, Frequency
|
||||
, qint32 drift, QString const& callsign, QString const& grid, qint32 power);
|
||||
Q_SLOT void clear_decodes ();
|
||||
Q_SLOT void qso_logged (QDateTime time, QString const& dx_call, QString const& dx_grid
|
||||
, Frequency dial_frequency, QString const& mode, QString const& report_sent
|
||||
|
@ -223,6 +223,27 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
|
||||
}
|
||||
break;
|
||||
|
||||
case NetworkMessage::WSPRDecode:
|
||||
{
|
||||
// unpack message
|
||||
bool is_new {true};
|
||||
QTime time;
|
||||
qint32 snr;
|
||||
float delta_time;
|
||||
Frequency frequency;
|
||||
qint32 drift;
|
||||
QByteArray callsign;
|
||||
QByteArray grid;
|
||||
qint32 power;
|
||||
in >> is_new >> time >> snr >> delta_time >> frequency >> drift >> callsign >> grid >> power;
|
||||
if (check_status (in) != Fail)
|
||||
{
|
||||
Q_EMIT self_->WSPR_decode (is_new, id, time, snr, delta_time, frequency, drift
|
||||
, QString::fromUtf8 (callsign), QString::fromUtf8 (grid), power);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NetworkMessage::QSOLogged:
|
||||
{
|
||||
QDateTime time;
|
||||
|
@ -65,6 +65,8 @@ public:
|
||||
Q_SIGNAL void client_closed (QString const& id);
|
||||
Q_SIGNAL void decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time
|
||||
, quint32 delta_frequency, QString const& mode, QString const& message);
|
||||
Q_SIGNAL void WSPR_decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time, Frequency
|
||||
, qint32 drift, QString const& callsign, QString const& grid, qint32 power);
|
||||
Q_SIGNAL void qso_logged (QString const& id, QDateTime time, QString const& dx_call, QString const& dx_grid
|
||||
, Frequency dial_frequency, QString const& mode, QString const& report_sent
|
||||
, QString const& report_received, QString const& tx_power, QString const& comments
|
||||
|
@ -137,7 +137,7 @@
|
||||
* Mode utf8
|
||||
* Message utf8
|
||||
*
|
||||
* The decode message is send when a new decode is completed, in
|
||||
* The decode message is sent when a new decode is completed, in
|
||||
* this case the 'New' field is true. It is also used in response
|
||||
* to a "Replay" message where each old decode in the "Band
|
||||
* activity" window, that has not been erased, is sent in order
|
||||
@ -260,6 +260,26 @@
|
||||
* command to determine the contents of the current free text
|
||||
* message.
|
||||
*
|
||||
* WSPRDecode Out 10 quint32
|
||||
* Id (unique key) utf8
|
||||
* New bool
|
||||
* Time QTime
|
||||
* snr qint32
|
||||
* Delta time (S) float (serialized as double)
|
||||
* Frequency (Hz) quint64
|
||||
* Drift (Hz) qint32
|
||||
* Callsign utf8
|
||||
* Grid utf8
|
||||
* Power (dBm) qint32
|
||||
*
|
||||
* The decode message is sent when a new decode is completed, in
|
||||
* this case the 'New' field is true. It is also used in response
|
||||
* to a "Replay" message where each old decode in the "Band
|
||||
* activity" window, that has not been erased, is sent in order
|
||||
* as a one of these messages with the 'New' field set to
|
||||
* false. See the "Replay" message below for details of usage.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <QDataStream>
|
||||
@ -285,6 +305,7 @@ namespace NetworkMessage
|
||||
Replay,
|
||||
HaltTx,
|
||||
FreeText,
|
||||
WSPRDecode,
|
||||
maximum_message_type_ // ONLY add new message types
|
||||
// immediately before here
|
||||
};
|
||||
|
@ -870,6 +870,10 @@ void MainWindow::dataSink(qint64 frames)
|
||||
cmnd=t3.mid(0,i1+7) + t3.mid(i1+7);
|
||||
ui->DecodeButton->setChecked (true);
|
||||
p1.start(QDir::toNativeSeparators(cmnd));
|
||||
m_messageClient->status_update (m_dialFreq, m_mode, m_hisCall,
|
||||
QString::number (ui->rptSpinBox->value ()),
|
||||
m_modeTx, ui->autoButton->isChecked (),
|
||||
m_transmitting, (m_decoderBusy = true));
|
||||
}
|
||||
m_rxDone=true;
|
||||
}
|
||||
@ -1012,7 +1016,7 @@ void MainWindow::keyPressEvent( QKeyEvent *e ) //keyPressEvent
|
||||
switch(e->key())
|
||||
{
|
||||
case Qt::Key_D:
|
||||
if(e->modifiers() & Qt::ShiftModifier) {
|
||||
if(m_mode != "WSPR-2" && e->modifiers() & Qt::ShiftModifier) {
|
||||
if(!m_decoderBusy) {
|
||||
jt9com_.newdat=0;
|
||||
jt9com_.nagain=0;
|
||||
@ -1463,7 +1467,7 @@ void MainWindow::on_actionSpecial_mouse_commands_triggered()
|
||||
|
||||
void MainWindow::on_DecodeButton_clicked (bool /* checked */) //Decode request
|
||||
{
|
||||
if(!m_decoderBusy) {
|
||||
if(m_mode != "WSPR-2" && !m_decoderBusy) {
|
||||
jt9com_.newdat=0;
|
||||
jt9com_.nagain=1;
|
||||
m_blankLine=false; // don't insert the separator again
|
||||
@ -3925,17 +3929,27 @@ void MainWindow::replayDecodes ()
|
||||
{
|
||||
// we accept this request even if the setting to accept UDP requests
|
||||
// is not checked
|
||||
|
||||
// attempt to parse the decoded text
|
||||
Q_FOREACH (auto const& message, ui->decodedTextBrowser->toPlainText ().split ('\n', QString::SkipEmptyParts))
|
||||
{
|
||||
if (message.size() >= 4 && message.left (4) != "----")
|
||||
{
|
||||
auto eom_pos = message.indexOf (' ', 35);
|
||||
// we always want at least the characters to position 35
|
||||
if (eom_pos < 35)
|
||||
auto const& parts = message.split (' ', QString::SkipEmptyParts);
|
||||
if (parts.size () >= 5 && parts[3].contains ('.')) // WSPR
|
||||
{
|
||||
eom_pos = message.size () - 1;
|
||||
postWSPRDecode (false, parts);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto eom_pos = message.indexOf (' ', 35);
|
||||
// we always want at least the characters to position 35
|
||||
if (eom_pos < 35)
|
||||
{
|
||||
eom_pos = message.size () - 1;
|
||||
}
|
||||
postDecode (false, message.left (eom_pos + 1));
|
||||
}
|
||||
postDecode (false, message.left (eom_pos + 1));
|
||||
}
|
||||
}
|
||||
statusChanged ();
|
||||
@ -3943,8 +3957,8 @@ void MainWindow::replayDecodes ()
|
||||
|
||||
void MainWindow::postDecode (bool is_new, QString const& message)
|
||||
{
|
||||
auto decode = message.trimmed ();
|
||||
auto parts = decode.left (21).split (' ', QString::SkipEmptyParts);
|
||||
auto const& decode = message.trimmed ();
|
||||
auto const& parts = decode.left (21).split (' ', QString::SkipEmptyParts);
|
||||
if (parts.size () >= 5)
|
||||
{
|
||||
m_messageClient->decode (is_new, QTime::fromString (parts[0], "hhmm"), parts[1].toInt ()
|
||||
@ -3952,6 +3966,18 @@ void MainWindow::postDecode (bool is_new, QString const& message)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::postWSPRDecode (bool is_new, QStringList parts)
|
||||
{
|
||||
if (parts.size () < 8)
|
||||
{
|
||||
parts.insert (6, "");
|
||||
}
|
||||
m_messageClient->WSPR_decode (is_new, QTime::fromString (parts[0], "hhmm"), parts[1].toInt ()
|
||||
, parts[2].toFloat (), Radio::frequency (parts[3].toFloat (), 6)
|
||||
, parts[4].toInt (), parts[5].remove ("<").remove (">")
|
||||
, parts[6], parts[7].toInt ());
|
||||
}
|
||||
|
||||
void MainWindow::networkError (QString const& e)
|
||||
{
|
||||
if (QMessageBox::Retry == QMessageBox::warning (this, tr ("Network Error")
|
||||
@ -4016,7 +4042,10 @@ void MainWindow::p1ReadFromStdout() //p1readFromStdout
|
||||
m_RxLog=0;
|
||||
m_startAnother=m_loopall;
|
||||
m_blankLine=true;
|
||||
return;
|
||||
m_messageClient->status_update (m_dialFreq, m_mode, m_hisCall,
|
||||
QString::number (ui->rptSpinBox->value ()),
|
||||
m_modeTx, ui->autoButton->isChecked (),
|
||||
m_transmitting, (m_decoderBusy = false));
|
||||
} else {
|
||||
|
||||
int n=t.length();
|
||||
@ -4035,6 +4064,7 @@ void MainWindow::p1ReadFromStdout() //p1readFromStdout
|
||||
.arg(rxFields.at(5).leftJustified (12).replace ('<', "<").replace ('>', ">"))
|
||||
.arg(rxFields.at(6), -6)
|
||||
.arg(rxFields.at(7), 3);
|
||||
postWSPRDecode (true, rxFields);
|
||||
grid = rxFields.at(6);
|
||||
} else if ( rxFields.count() == 7 ) { // Type 2 message
|
||||
rxLine = QString("%1 %2 %3 %4 %5 %6 %7 %8")
|
||||
@ -4046,6 +4076,7 @@ void MainWindow::p1ReadFromStdout() //p1readFromStdout
|
||||
.arg(rxFields.at(5).leftJustified (12).replace ('<', "<").replace ('>', ">"))
|
||||
.arg("", -6)
|
||||
.arg(rxFields.at(6), 3);
|
||||
postWSPRDecode (true, rxFields);
|
||||
} else {
|
||||
rxLine = t;
|
||||
}
|
||||
|
@ -501,6 +501,7 @@ private:
|
||||
void replyToCQ (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text);
|
||||
void replayDecodes ();
|
||||
void postDecode (bool is_new, QString const& message);
|
||||
void postWSPRDecode (bool is_new, QStringList message_parts);
|
||||
void enable_DXCC_entity (bool on);
|
||||
void switch_mode (Mode);
|
||||
void WSPR_scheduling ();
|
||||
|
Loading…
Reference in New Issue
Block a user