mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-21 11:31:51 -05:00
Make the UDP protocol Clear (3) message two-way
External servers can clear either or both of the Band Activity and Rx Frequency decodes windows. This was requested by Dave, AA6YQ, so that DX Lab Suite applications can clear old decodes on band changes to ensure that decode highlighing is consistent.
This commit is contained in:
parent
846918e3aa
commit
4dfc4685e9
@ -188,6 +188,18 @@ void MessageClient::impl::parse_message (QByteArray const& msg)
|
||||
}
|
||||
break;
|
||||
|
||||
case NetworkMessage::Clear:
|
||||
{
|
||||
quint8 window {0};
|
||||
in >> window;
|
||||
TRACE_UDP ("Clear window:" << window);
|
||||
if (check_status (in) != Fail)
|
||||
{
|
||||
Q_EMIT self_->clear_decodes (window);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NetworkMessage::Replay:
|
||||
TRACE_UDP ("Replay");
|
||||
if (check_status (in) != Fail)
|
||||
@ -477,7 +489,7 @@ void MessageClient::WSPR_decode (bool is_new, QTime time, qint32 snr, float delt
|
||||
}
|
||||
}
|
||||
|
||||
void MessageClient::clear_decodes ()
|
||||
void MessageClient::decodes_cleared ()
|
||||
{
|
||||
if (m_->server_port_ && !m_->server_string_.isEmpty ())
|
||||
{
|
||||
|
@ -59,7 +59,7 @@ public:
|
||||
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
|
||||
, bool off_air);
|
||||
Q_SLOT void clear_decodes ();
|
||||
Q_SLOT void decodes_cleared ();
|
||||
Q_SLOT void qso_logged (QDateTime time_off, 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
|
||||
@ -80,6 +80,10 @@ public:
|
||||
// with send_raw_datagram() above)
|
||||
Q_SLOT void add_blocked_destination (QHostAddress const&);
|
||||
|
||||
// this signal is emitted if the server has requested a decode
|
||||
// window clear action
|
||||
Q_SIGNAL void clear_decodes (quint8 window);
|
||||
|
||||
// this signal is emitted if the server sends us a reply, the only
|
||||
// reply supported is reply to a prior CQ or QRZ message
|
||||
Q_SIGNAL void reply (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode
|
||||
|
@ -224,7 +224,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
|
||||
break;
|
||||
|
||||
case NetworkMessage::Clear:
|
||||
Q_EMIT self_->clear_decodes (id);
|
||||
Q_EMIT self_->decodes_cleared (id);
|
||||
break;
|
||||
|
||||
case NetworkMessage::Status:
|
||||
@ -455,6 +455,18 @@ void MessageServer::start (port_type port, QHostAddress const& multicast_group_a
|
||||
}
|
||||
}
|
||||
|
||||
void MessageServer::clear_decodes (QString const& id, quint8 window)
|
||||
{
|
||||
auto iter = m_->clients_.find (id);
|
||||
if (iter != std::end (m_->clients_))
|
||||
{
|
||||
QByteArray message;
|
||||
NetworkMessage::Builder out {&message, NetworkMessage::Clear, id, (*iter).negotiated_schema_number_};
|
||||
out << window;
|
||||
m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageServer::reply (QString const& id, QTime time, qint32 snr, float delta_time
|
||||
, quint32 delta_frequency, QString const& mode
|
||||
, QString const& message_text, bool low_confidence, quint8 modifiers)
|
||||
|
@ -41,6 +41,9 @@ public:
|
||||
Q_SLOT void start (port_type port,
|
||||
QHostAddress const& multicast_group_address = QHostAddress {});
|
||||
|
||||
// ask the client to clear one or both of the decode windows
|
||||
Q_SLOT void clear_decodes (QString const& id, quint8 window = 0);
|
||||
|
||||
// ask the client with identification 'id' to make the same action
|
||||
// as a double click on the decode would
|
||||
//
|
||||
@ -91,7 +94,7 @@ public:
|
||||
, QString const& name, QDateTime time_on, QString const& operator_call
|
||||
, QString const& my_call, QString const& my_grid
|
||||
, QString const& exchange_sent, QString const& exchange_rcvd);
|
||||
Q_SIGNAL void clear_decodes (QString const& id);
|
||||
Q_SIGNAL void decodes_cleared (QString const& id);
|
||||
Q_SIGNAL void logged_ADIF (QString const& id, QByteArray const& ADIF);
|
||||
|
||||
// this signal is emitted when a network error occurs
|
||||
|
@ -186,16 +186,26 @@
|
||||
* back a .WAV file.
|
||||
*
|
||||
*
|
||||
* Clear Out 3 quint32
|
||||
* Clear Out/In 3 quint32
|
||||
* Id (unique key) utf8
|
||||
* Window quint8 (In only)
|
||||
*
|
||||
* This message is send when all prior "Decode" messages in the
|
||||
* "Band activity" window have been discarded and therefore are
|
||||
* "Band Activity" window have been discarded and therefore are
|
||||
* no long available for actioning with a "Reply" message. It is
|
||||
* sent when the user erases the "Band activity" window and when
|
||||
* WSJT-X closes down normally. The server should discard all
|
||||
* decode messages upon receipt of this message.
|
||||
*
|
||||
* It may also be sent to a WSJT-X instance in which case it
|
||||
* clears one or both of the "Band Activity" and "Rx Frequency"
|
||||
* windows. The Window argument can be one of the following
|
||||
* values:
|
||||
*
|
||||
* 0 - clear the "Band Activity" window (default)
|
||||
* 1 - clear the "Rx Frequency" window
|
||||
* 2 - clear both "Band Activity" and "Rx Frequency" windows
|
||||
*
|
||||
*
|
||||
* Reply In 4 quint32
|
||||
* Id (target unique key) utf8
|
||||
|
@ -121,7 +121,7 @@ void BeaconsModel::add_beacon_spot (bool is_new, QString const& client_id, QTime
|
||||
appendRow (make_row (client_id, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air));
|
||||
}
|
||||
|
||||
void BeaconsModel::clear_decodes (QString const& client_id)
|
||||
void BeaconsModel::decodes_cleared (QString const& client_id)
|
||||
{
|
||||
for (auto row = rowCount () - 1; row >= 0; --row)
|
||||
{
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
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, bool off_air);
|
||||
Q_SLOT void clear_decodes (QString const& client_id);
|
||||
Q_SLOT void decodes_cleared (QString const& client_id);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <QRegExp>
|
||||
#include <QColor>
|
||||
#include <QAction>
|
||||
|
||||
#include "validators/MaidenheadLocatorValidator.hpp"
|
||||
|
||||
@ -120,6 +121,9 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
|
||||
, id_ {id}
|
||||
, calls_of_interest_ {calls_of_interest}
|
||||
, decodes_proxy_model_ {id_}
|
||||
, erase_action_ {new QAction {tr ("&Erase Band Activity"), this}}
|
||||
, erase_rx_frequency_action_ {new QAction {tr ("Erase &Rx Frequency"), this}}
|
||||
, erase_both_action_ {new QAction {tr ("Erase &Both"), this}}
|
||||
, decodes_table_view_ {new QTableView}
|
||||
, beacons_table_view_ {new QTableView}
|
||||
, message_line_edit_ {new QLineEdit}
|
||||
@ -143,6 +147,10 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
|
||||
decodes_table_view_->verticalHeader ()->hide ();
|
||||
decodes_table_view_->hideColumn (0);
|
||||
decodes_table_view_->horizontalHeader ()->setStretchLastSection (true);
|
||||
decodes_table_view_->setContextMenuPolicy (Qt::ActionsContextMenu);
|
||||
decodes_table_view_->insertAction (nullptr, erase_action_);
|
||||
decodes_table_view_->insertAction (nullptr, erase_rx_frequency_action_);
|
||||
decodes_table_view_->insertAction (nullptr, erase_both_action_);
|
||||
|
||||
auto form_layout = new QFormLayout;
|
||||
form_layout->addRow (tr ("Free text:"), message_line_edit_);
|
||||
@ -171,6 +179,8 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
|
||||
beacons_table_view_->verticalHeader ()->hide ();
|
||||
beacons_table_view_->hideColumn (0);
|
||||
beacons_table_view_->horizontalHeader ()->setStretchLastSection (true);
|
||||
beacons_table_view_->setContextMenuPolicy (Qt::ActionsContextMenu);
|
||||
beacons_table_view_->insertAction (nullptr, erase_action_);
|
||||
|
||||
auto beacons_page = new QWidget;
|
||||
auto beacons_layout = new QVBoxLayout {beacons_page};
|
||||
@ -219,8 +229,19 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
|
||||
setAllowedAreas (Qt::BottomDockWidgetArea);
|
||||
setFloating (true);
|
||||
|
||||
// connect context menu actions
|
||||
connect (erase_action_, &QAction::triggered, [this] (bool /*checked*/) {
|
||||
Q_EMIT do_clear_decodes (id_);
|
||||
});
|
||||
connect (erase_rx_frequency_action_, &QAction::triggered, [this] (bool /*checked*/) {
|
||||
Q_EMIT do_clear_decodes (id_, 1);
|
||||
});
|
||||
connect (erase_both_action_, &QAction::triggered, [this] (bool /*checked*/) {
|
||||
Q_EMIT do_clear_decodes (id_, 2);
|
||||
});
|
||||
|
||||
// connect up table view signals
|
||||
connect (decodes_table_view_, &QTableView::doubleClicked, this, [this] (QModelIndex const& index) {
|
||||
connect (decodes_table_view_, &QTableView::doubleClicked, [this] (QModelIndex const& index) {
|
||||
Q_EMIT do_reply (decodes_proxy_model_.mapToSource (index), QApplication::keyboardModifiers () >> 24);
|
||||
});
|
||||
|
||||
@ -313,7 +334,7 @@ void ClientWidget::beacon_spot_added (bool /*is_new*/, QString const& client_id,
|
||||
beacons_table_view_->scrollToBottom ();
|
||||
}
|
||||
|
||||
void ClientWidget::clear_decodes (QString const& client_id)
|
||||
void ClientWidget::decodes_cleared (QString const& client_id)
|
||||
{
|
||||
if (client_id == id_)
|
||||
{
|
||||
|
@ -12,6 +12,7 @@
|
||||
class QAbstractItemModel;
|
||||
class QModelIndex;
|
||||
class QColor;
|
||||
class QAction;
|
||||
|
||||
using Frequency = MessageServer::Frequency;
|
||||
|
||||
@ -41,8 +42,9 @@ public:
|
||||
, float delta_time, Frequency delta_frequency, qint32 drift
|
||||
, QString const& callsign, QString const& grid, qint32 power
|
||||
, bool off_air);
|
||||
Q_SLOT void clear_decodes (QString const& client_id);
|
||||
Q_SLOT void decodes_cleared (QString const& client_id);
|
||||
|
||||
Q_SIGNAL void do_clear_decodes (QString const& id, quint8 window = 0);
|
||||
Q_SIGNAL void do_reply (QModelIndex const&, quint8 modifier);
|
||||
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);
|
||||
@ -74,6 +76,9 @@ private:
|
||||
QRegularExpression base_call_re_;
|
||||
int rx_df_;
|
||||
} decodes_proxy_model_;
|
||||
QAction * erase_action_;
|
||||
QAction * erase_rx_frequency_action_;
|
||||
QAction * erase_both_action_;
|
||||
QTableView * decodes_table_view_;
|
||||
QTableView * beacons_table_view_;
|
||||
QLineEdit * message_line_edit_;
|
||||
|
@ -125,7 +125,7 @@ void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time
|
||||
, off_air, is_fast));
|
||||
}
|
||||
|
||||
void DecodesModel::clear_decodes (QString const& client_id)
|
||||
void DecodesModel::decodes_cleared (QString const& client_id)
|
||||
{
|
||||
for (auto row = rowCount () - 1; row >= 0; --row)
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ public:
|
||||
Q_SLOT void add_decode (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time
|
||||
, quint32 delta_frequency, QString const& mode, QString const& message
|
||||
, bool low_confidence, bool off_air, bool is_fast);
|
||||
Q_SLOT void clear_decodes (QString const& client_id);
|
||||
Q_SLOT void decodes_cleared (QString const& client_id);
|
||||
Q_SLOT void do_reply (QModelIndex const& source, quint8 modifiers);
|
||||
|
||||
Q_SIGNAL void reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency
|
||||
|
@ -181,8 +181,8 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow ()
|
||||
});
|
||||
connect (server_, &MessageServer::client_opened, this, &MessageAggregatorMainWindow::add_client);
|
||||
connect (server_, &MessageServer::client_closed, this, &MessageAggregatorMainWindow::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::client_closed, decodes_model_, &DecodesModel::decodes_cleared);
|
||||
connect (server_, &MessageServer::client_closed, beacons_model_, &BeaconsModel::decodes_cleared);
|
||||
connect (server_, &MessageServer::decode, [this] (bool is_new, QString const& id, QTime time
|
||||
, qint32 snr, float delta_time
|
||||
, quint32 delta_frequency, QString const& mode
|
||||
@ -191,8 +191,8 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow ()
|
||||
decodes_model_->add_decode (is_new, id, time, snr, delta_time, delta_frequency, mode, message
|
||||
, low_confidence, off_air, dock_widgets_[id]->fast_mode ());});
|
||||
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 (server_, &MessageServer::decodes_cleared, decodes_model_, &DecodesModel::decodes_cleared);
|
||||
connect (server_, &MessageServer::decodes_cleared, beacons_model_, &BeaconsModel::decodes_cleared);
|
||||
connect (decodes_model_, &DecodesModel::reply, server_, &MessageServer::reply);
|
||||
|
||||
// UI behaviour
|
||||
@ -248,7 +248,8 @@ void MessageAggregatorMainWindow::add_client (QString const& id, QString const&
|
||||
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 (server_, &MessageServer::clear_decodes, dock, &ClientWidget::clear_decodes);
|
||||
connect (server_, &MessageServer::decodes_cleared, dock, &ClientWidget::decodes_cleared);
|
||||
connect (dock, &ClientWidget::do_clear_decodes, server_, &MessageServer::clear_decodes);
|
||||
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);
|
||||
|
@ -487,6 +487,17 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
});
|
||||
|
||||
// Network message handlers
|
||||
connect (m_messageClient, &MessageClient::clear_decodes, [this] (quint8 window) {
|
||||
++window;
|
||||
if (window & 1)
|
||||
{
|
||||
ui->decodedTextBrowser->erase ();
|
||||
}
|
||||
if (window & 2)
|
||||
{
|
||||
ui->decodedTextBrowser2->erase ();
|
||||
}
|
||||
});
|
||||
connect (m_messageClient, &MessageClient::reply, this, &MainWindow::replyToCQ);
|
||||
connect (m_messageClient, &MessageClient::replay, this, &MainWindow::replayDecodes);
|
||||
connect (m_messageClient, &MessageClient::location, this, &MainWindow::locationChange);
|
||||
@ -3310,7 +3321,7 @@ void MainWindow::on_EraseButton_clicked ()
|
||||
|
||||
void MainWindow::band_activity_cleared ()
|
||||
{
|
||||
m_messageClient->clear_decodes ();
|
||||
m_messageClient->decodes_cleared ();
|
||||
QFile f(m_config.temp_dir ().absoluteFilePath ("decoded.txt"));
|
||||
if(f.exists()) f.remove();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user