diff --git a/UDPExamples/BeaconsModel.cpp b/UDPExamples/BeaconsModel.cpp index 7ac1323a1..8a6cdd279 100644 --- a/UDPExamples/BeaconsModel.cpp +++ b/UDPExamples/BeaconsModel.cpp @@ -25,10 +25,13 @@ namespace QFont text_font {"Courier", 10}; - QList make_row (QString const& client_id, QTime time, qint32 snr, float delta_time + QList make_row (MessageServer::ClientKey const& key, QTime time, qint32 snr, float delta_time , Frequency frequency, qint32 drift, QString const& callsign , QString const& grid, qint32 power, bool off_air) { + auto client_item = new QStandardItem {QString {"%1(%2)"}.arg (key.second).arg (key.first.toString ())}; + client_item->setData (QVariant::fromValue (key)); + auto time_item = new QStandardItem {time.toString ("hh:mm")}; time_item->setData (time); time_item->setTextAlignment (Qt::AlignRight); @@ -60,7 +63,7 @@ namespace live->setTextAlignment (Qt::AlignHCenter); QList row { - new QStandardItem {client_id}, time_item, snr_item, dt, freq, dri, gd, pwr, live, new QStandardItem {callsign}}; + client_item, time_item, snr_item, dt, freq, dri, gd, pwr, live, new QStandardItem {callsign}}; Q_FOREACH (auto& item, row) { item->setEditable (false); @@ -81,7 +84,7 @@ BeaconsModel::BeaconsModel (QObject * parent) } } -void BeaconsModel::add_beacon_spot (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time +void BeaconsModel::add_beacon_spot (bool is_new, ClientKey const& key, QTime time, qint32 snr, float delta_time , Frequency frequency, qint32 drift, QString const& callsign , QString const& grid, qint32 power, bool off_air) { @@ -90,7 +93,7 @@ void BeaconsModel::add_beacon_spot (bool is_new, QString const& client_id, QTime int target_row {-1}; for (auto row = 0; row < rowCount (); ++row) { - if (data (index (row, 0)).toString () == client_id) + if (item (row, 0)->data ().value () == key) { auto row_time = item (row, 1)->data ().toTime (); if (row_time == time @@ -113,19 +116,19 @@ void BeaconsModel::add_beacon_spot (bool is_new, QString const& client_id, QTime } if (target_row >= 0) { - insertRow (target_row + 1, make_row (client_id, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air)); + insertRow (target_row + 1, make_row (key, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air)); return; } } - appendRow (make_row (client_id, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air)); + appendRow (make_row (key, time, snr, delta_time, frequency, drift, callsign, grid, power, off_air)); } -void BeaconsModel::decodes_cleared (QString const& client_id) +void BeaconsModel::decodes_cleared (ClientKey const& key) { for (auto row = rowCount () - 1; row >= 0; --row) { - if (data (index (row, 0)).toString () == client_id) + if (item (row, 0)->data ().value () == key) { removeRow (row); } diff --git a/UDPExamples/BeaconsModel.hpp b/UDPExamples/BeaconsModel.hpp index b089349cc..2baa99ec3 100644 --- a/UDPExamples/BeaconsModel.hpp +++ b/UDPExamples/BeaconsModel.hpp @@ -26,13 +26,15 @@ class BeaconsModel { Q_OBJECT; + using ClientKey = MessageServer::ClientKey; + public: explicit BeaconsModel (QObject * parent = nullptr); - Q_SLOT void add_beacon_spot (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time + Q_SLOT void add_beacon_spot (bool is_new, ClientKey const&, 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 decodes_cleared (QString const& client_id); + Q_SLOT void decodes_cleared (ClientKey const&); }; #endif diff --git a/UDPExamples/ClientWidget.cpp b/UDPExamples/ClientWidget.cpp index b2ee03609..3be8c788c 100644 --- a/UDPExamples/ClientWidget.cpp +++ b/UDPExamples/ClientWidget.cpp @@ -27,9 +27,9 @@ namespace } } -ClientWidget::IdFilterModel::IdFilterModel (QString const& client_id, QObject * parent) +ClientWidget::IdFilterModel::IdFilterModel (ClientKey const& key, QObject * parent) : QSortFilterProxyModel {parent} - , client_id_ {client_id} + , key_ {key} , rx_df_ (quint32_max) { } @@ -73,7 +73,7 @@ bool ClientWidget::IdFilterModel::filterAcceptsRow (int source_row , QModelIndex const& source_parent) const { auto source_index_col0 = sourceModel ()->index (source_row, 0, source_parent); - return sourceModel ()->data (source_index_col0).toString () == client_id_; + return sourceModel ()->data (source_index_col0).value () == key_; } void ClientWidget::IdFilterModel::de_call (QString const& call) @@ -106,9 +106,9 @@ void ClientWidget::IdFilterModel::rx_df (quint32 df) namespace { - QString make_title (QString const& id, QString const& version, QString const& revision) + QString make_title (MessageServer::ClientKey const& key, QString const& version, QString const& revision) { - QString title {id}; + QString title {QString {"%1(%2)"}.arg (key.second).arg (key.first.toString ())}; if (version.size ()) { title += QString {" v%1"}.arg (version); @@ -122,14 +122,14 @@ namespace } ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model - , QString const& id, QString const& version, QString const& revision + , ClientKey const& key, QString const& version, QString const& revision , QListWidget const * calls_of_interest, QWidget * parent) - : QDockWidget {make_title (id, version, revision), parent} - , id_ {id} + : QDockWidget {make_title (key, version, revision), parent} + , key_ {key} , done_ {false} , calls_of_interest_ {calls_of_interest} - , decodes_proxy_model_ {id} - , beacons_proxy_model_ {id} + , decodes_proxy_model_ {key} + , beacons_proxy_model_ {key} , 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}} @@ -209,56 +209,56 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod horizontal_layout_->addLayout (subform3_layout_); connect (message_line_edit_, &QLineEdit::textEdited, [this] (QString const& text) { - Q_EMIT do_free_text (id_, text, false); + Q_EMIT do_free_text (key_, text, false); }); connect (message_line_edit_, &QLineEdit::editingFinished, [this] () { - Q_EMIT do_free_text (id_, message_line_edit_->text (), true); + Q_EMIT do_free_text (key_, message_line_edit_->text (), true); }); connect (grid_line_edit_, &QLineEdit::editingFinished, [this] () { - Q_EMIT location (id_, grid_line_edit_->text ()); + Q_EMIT location (key_, grid_line_edit_->text ()); }); connect (configuration_line_edit_, &QLineEdit::editingFinished, [this] () { - Q_EMIT switch_configuration (id_, configuration_line_edit_->text ()); + Q_EMIT switch_configuration (key_, configuration_line_edit_->text ()); }); connect (mode_line_edit_, &QLineEdit::editingFinished, [this] () { QString empty; - Q_EMIT configure (id_, mode_line_edit_->text (), quint32_max, empty, fast_mode () + Q_EMIT configure (key_, mode_line_edit_->text (), quint32_max, empty, fast_mode () , quint32_max, quint32_max, empty, empty, false); }); connect (frequency_tolerance_spin_box_, static_cast (&QSpinBox::valueChanged), [this] (int i) { QString empty; auto f = frequency_tolerance_spin_box_->specialValueText ().size () ? quint32_max : i; - Q_EMIT configure (id_, empty, f, empty, fast_mode () + Q_EMIT configure (key_, empty, f, empty, fast_mode () , quint32_max, quint32_max, empty, empty, false); }); connect (submode_line_edit_, &QLineEdit::editingFinished, [this] () { QString empty; - Q_EMIT configure (id_, empty, quint32_max, submode_line_edit_->text (), fast_mode () + Q_EMIT configure (key_, empty, quint32_max, submode_line_edit_->text (), fast_mode () , quint32_max, quint32_max, empty, empty, false); }); connect (fast_mode_check_box_, &QCheckBox::stateChanged, [this] (int state) { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, Qt::Checked == state + Q_EMIT configure (key_, empty, quint32_max, empty, Qt::Checked == state , quint32_max, quint32_max, empty, empty, false); }); connect (tr_period_spin_box_, static_cast (&QSpinBox::valueChanged), [this] (int i) { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , i, quint32_max, empty, empty, false); }); connect (rx_df_spin_box_, static_cast (&QSpinBox::valueChanged), [this] (int i) { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , quint32_max, i, empty, empty, false); }); connect (dx_call_line_edit_, &QLineEdit::editingFinished, [this] () { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , quint32_max, quint32_max, dx_call_line_edit_->text (), empty, false); }); connect (dx_grid_line_edit_, &QLineEdit::editingFinished, [this] () { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , quint32_max, quint32_max, empty, dx_grid_line_edit_->text (), false); }); @@ -289,14 +289,14 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod halt_tx_button_ = control_button_box_->addButton (tr ("&Halt Tx"), QDialogButtonBox::ActionRole); connect (generate_messages_push_button_, &QAbstractButton::clicked, [this] (bool /*checked*/) { QString empty; - Q_EMIT configure (id_, empty, quint32_max, empty, fast_mode () + Q_EMIT configure (key_, empty, quint32_max, empty, fast_mode () , quint32_max, quint32_max, empty, empty, true); }); connect (auto_off_button_, &QAbstractButton::clicked, [this] (bool /* checked */) { - Q_EMIT do_halt_tx (id_, true); + Q_EMIT do_halt_tx (key_, true); }); connect (halt_tx_button_, &QAbstractButton::clicked, [this] (bool /* checked */) { - Q_EMIT do_halt_tx (id_, false); + Q_EMIT do_halt_tx (key_, false); }); content_layout_->addWidget (control_button_box_); @@ -318,13 +318,13 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod // connect context menu actions connect (erase_action_, &QAction::triggered, [this] (bool /*checked*/) { - Q_EMIT do_clear_decodes (id_); + Q_EMIT do_clear_decodes (key_); }); connect (erase_rx_frequency_action_, &QAction::triggered, [this] (bool /*checked*/) { - Q_EMIT do_clear_decodes (id_, 1); + Q_EMIT do_clear_decodes (key_, 1); }); connect (erase_both_action_, &QAction::triggered, [this] (bool /*checked*/) { - Q_EMIT do_clear_decodes (id_, 2); + Q_EMIT do_clear_decodes (key_, 2); }); // connect up table view signals @@ -335,7 +335,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod // tell new client about calls of interest for (int row = 0; row < calls_of_interest_->count (); ++row) { - Q_EMIT highlight_callsign (id_, calls_of_interest_->item (row)->text (), QColor {Qt::blue}, QColor {Qt::yellow}); + Q_EMIT highlight_callsign (key_, calls_of_interest_->item (row)->text (), QColor {Qt::blue}, QColor {Qt::yellow}); } } @@ -349,7 +349,7 @@ void ClientWidget::closeEvent (QCloseEvent *e) { if (!done_) { - Q_EMIT do_close (id_); + Q_EMIT do_close (key_); e->ignore (); // defer closure until client actually closes } else @@ -363,7 +363,7 @@ ClientWidget::~ClientWidget () for (int row = 0; row < calls_of_interest_->count (); ++row) { // tell client to forget calls of interest - Q_EMIT highlight_callsign (id_, calls_of_interest_->item (row)->text ()); + Q_EMIT highlight_callsign (key_, calls_of_interest_->item (row)->text ()); } } @@ -395,7 +395,7 @@ namespace } } -void ClientWidget::update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call +void ClientWidget::update_status (ClientKey const& key, Frequency f, QString const& mode, QString const& dx_call , QString const& report, QString const& tx_mode, bool tx_enabled , bool transmitting, bool decoding, quint32 rx_df, quint32 tx_df , QString const& de_call, QString const& de_grid, QString const& dx_grid @@ -403,7 +403,7 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const& , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period , QString const& configuration_name) { - if (id == id_) + if (key == key_) { fast_mode_check_box_->setChecked (fast_mode); decodes_proxy_model_.de_call (de_call); @@ -447,11 +447,11 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const& } } -void ClientWidget::decode_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/ +void ClientWidget::decode_added (bool /*is_new*/, ClientKey const& key, QTime /*time*/, qint32 /*snr*/ , float /*delta_time*/, quint32 /*delta_frequency*/, QString const& /*mode*/ , QString const& /*message*/, bool /*low_confidence*/, bool /*off_air*/) { - if (client_id == id_ && !columns_resized_) + if (key == key_ && !columns_resized_) { decodes_stack_->setCurrentIndex (0); decodes_table_view_->resizeColumnsToContents (); @@ -460,12 +460,12 @@ void ClientWidget::decode_added (bool /*is_new*/, QString const& client_id, QTim decodes_table_view_->scrollToBottom (); } -void ClientWidget::beacon_spot_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/ +void ClientWidget::beacon_spot_added (bool /*is_new*/, ClientKey const& key, QTime /*time*/, qint32 /*snr*/ , float /*delta_time*/, Frequency /*delta_frequency*/, qint32 /*drift*/ , QString const& /*callsign*/, QString const& /*grid*/, qint32 /*power*/ , bool /*off_air*/) { - if (client_id == id_ && !columns_resized_) + if (key == key_ && !columns_resized_) { decodes_stack_->setCurrentIndex (1); beacons_table_view_->resizeColumnsToContents (); @@ -474,9 +474,9 @@ void ClientWidget::beacon_spot_added (bool /*is_new*/, QString const& client_id, beacons_table_view_->scrollToBottom (); } -void ClientWidget::decodes_cleared (QString const& client_id) +void ClientWidget::decodes_cleared (ClientKey const& key) { - if (client_id == id_) + if (key == key_) { columns_resized_ = false; } diff --git a/UDPExamples/ClientWidget.hpp b/UDPExamples/ClientWidget.hpp index 983ddd874..ee91d084a 100644 --- a/UDPExamples/ClientWidget.hpp +++ b/UDPExamples/ClientWidget.hpp @@ -35,42 +35,44 @@ class ClientWidget { Q_OBJECT; + using ClientKey = MessageServer::ClientKey; + public: explicit ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemModel * beacons_model - , QString const& id, QString const& version, QString const& revision + , ClientKey const& key, QString const& version, QString const& revision , QListWidget const * calls_of_interest, QWidget * parent = nullptr); void dispose (); ~ClientWidget (); bool fast_mode () const; - Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call + Q_SLOT void update_status (ClientKey const& key, Frequency f, QString const& mode, QString const& dx_call , QString const& report, QString const& tx_mode, bool tx_enabled , bool transmitting, bool decoding, quint32 rx_df, quint32 tx_df , QString const& de_call, QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& sub_mode, bool fast_mode , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period , QString const& configuration_name); - Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime, qint32 snr + Q_SLOT void decode_added (bool is_new, ClientKey const& key, QTime, qint32 snr , float delta_time, quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence, bool off_air); - Q_SLOT void beacon_spot_added (bool is_new, QString const& client_id, QTime, qint32 snr + Q_SLOT void beacon_spot_added (bool is_new, ClientKey const& key, QTime, qint32 snr , float delta_time, Frequency delta_frequency, qint32 drift , QString const& callsign, QString const& grid, qint32 power , bool off_air); - Q_SLOT void decodes_cleared (QString const& client_id); + Q_SLOT void decodes_cleared (ClientKey const& key); - Q_SIGNAL void do_clear_decodes (QString const& id, quint8 window = 0); - Q_SIGNAL void do_close (QString const& id); + Q_SIGNAL void do_clear_decodes (ClientKey const& key, quint8 window = 0); + Q_SIGNAL void do_close (ClientKey const& key); 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); - Q_SIGNAL void location (QString const& id, QString const& text); - Q_SIGNAL void highlight_callsign (QString const& id, QString const& call + Q_SIGNAL void do_halt_tx (ClientKey const& key, bool auto_only); + Q_SIGNAL void do_free_text (ClientKey const& key, QString const& text, bool); + Q_SIGNAL void location (ClientKey const& key, QString const& text); + Q_SIGNAL void highlight_callsign (ClientKey const& key, QString const& call , QColor const& bg = QColor {}, QColor const& fg = QColor {} , bool last_only = false); - Q_SIGNAL void switch_configuration (QString const& id, QString const& configuration_name); - Q_SIGNAL void configure (QString const& id, QString const& mode, quint32 frequency_tolerance + Q_SIGNAL void switch_configuration (ClientKey const& key, QString const& configuration_name); + Q_SIGNAL void configure (ClientKey const& key, QString const& mode, quint32 frequency_tolerance , QString const& submode, bool fast_mode, quint32 tr_period, quint32 rx_df , QString const& dx_call, QString const& dx_grid, bool generate_messages); @@ -79,7 +81,7 @@ private: : public QSortFilterProxyModel { public: - IdFilterModel (QString const& client_id, QObject * = nullptr); + IdFilterModel (ClientKey const& key, QObject * = nullptr); void de_call (QString const&); void rx_df (quint32); @@ -88,7 +90,7 @@ private: private: bool filterAcceptsRow (int source_row, QModelIndex const& source_parent) const override; - QString client_id_; + ClientKey key_; QString call_; QRegularExpression base_call_re_; quint32 rx_df_; @@ -96,7 +98,7 @@ private: void closeEvent (QCloseEvent *) override; - QString id_; + ClientKey key_; bool done_; QListWidget const * calls_of_interest_; IdFilterModel decodes_proxy_model_; diff --git a/UDPExamples/DecodesModel.cpp b/UDPExamples/DecodesModel.cpp index 6121ff31a..7b8d87c52 100644 --- a/UDPExamples/DecodesModel.cpp +++ b/UDPExamples/DecodesModel.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -33,10 +34,13 @@ namespace QFont text_font {"Courier", 10}; - QList make_row (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) + QList make_row (MessageServer::ClientKey const& key, 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) { + auto client_item = new QStandardItem {QString {"%1(%2)"}.arg (key.second).arg (key.first.toString ())}; + client_item->setData (QVariant::fromValue (key)); + auto time_item = new QStandardItem {time.toString (is_fast || "~" == mode ? "hh:mm:ss" : "hh:mm")}; time_item->setData (time); time_item->setTextAlignment (Qt::AlignRight); @@ -63,7 +67,7 @@ namespace live->setTextAlignment (Qt::AlignHCenter); QList row { - new QStandardItem {client_id}, time_item, snr_item, dt, df, md, confidence, live, new QStandardItem {message}}; + client_item, time_item, snr_item, dt, df, md, confidence, live, new QStandardItem {message}}; Q_FOREACH (auto& item, row) { item->setEditable (false); @@ -84,7 +88,7 @@ DecodesModel::DecodesModel (QObject * parent) } } -void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time +void DecodesModel::add_decode (bool is_new, ClientKey const& key, 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) { @@ -93,7 +97,7 @@ void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time int target_row {-1}; for (auto row = 0; row < rowCount (); ++row) { - if (data (index (row, 0)).toString () == client_id) + if (item (row, 0)->data ().value () == key) { auto row_time = item (row, 1)->data ().toTime (); if (row_time == time @@ -115,21 +119,21 @@ void DecodesModel::add_decode (bool is_new, QString const& client_id, QTime time } if (target_row >= 0) { - insertRow (target_row + 1, make_row (client_id, time, snr, delta_time, delta_frequency, mode + insertRow (target_row + 1, make_row (key, time, snr, delta_time, delta_frequency, mode , message, low_confidence, off_air, is_fast)); return; } } - appendRow (make_row (client_id, time, snr, delta_time, delta_frequency, mode, message, low_confidence + appendRow (make_row (key, time, snr, delta_time, delta_frequency, mode, message, low_confidence , off_air, is_fast)); } -void DecodesModel::decodes_cleared (QString const& client_id) +void DecodesModel::decodes_cleared (ClientKey const& key) { for (auto row = rowCount () - 1; row >= 0; --row) { - if (data (index (row, 0)).toString () == client_id) + if (item (row, 0)->data ().value () == key) { removeRow (row); } @@ -139,7 +143,7 @@ void DecodesModel::decodes_cleared (QString const& client_id) void DecodesModel::do_reply (QModelIndex const& source, quint8 modifiers) { auto row = source.row (); - Q_EMIT reply (data (index (row, 0)).toString () + Q_EMIT reply (item (row, 0)->data ().value () , item (row, 1)->data ().toTime () , item (row, 2)->data ().toInt () , item (row, 3)->data ().toFloat () diff --git a/UDPExamples/DecodesModel.hpp b/UDPExamples/DecodesModel.hpp index 17c9ae125..27a168c87 100644 --- a/UDPExamples/DecodesModel.hpp +++ b/UDPExamples/DecodesModel.hpp @@ -5,8 +5,6 @@ #include "MessageServer.hpp" -using Frequency = MessageServer::Frequency; - class QTime; class QString; class QModelIndex; @@ -28,16 +26,18 @@ class DecodesModel { Q_OBJECT; + using ClientKey = MessageServer::ClientKey; + public: explicit DecodesModel (QObject * parent = nullptr); - Q_SLOT void add_decode (bool is_new, QString const& client_id, QTime time, qint32 snr, float delta_time + Q_SLOT void add_decode (bool is_new, ClientKey const&, QTime, 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 decodes_cleared (QString const& client_id); + Q_SLOT void decodes_cleared (ClientKey const&); 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 + Q_SIGNAL void reply (ClientKey const&, QTime, qint32 snr, float delta_time, quint32 delta_frequency , QString const& mode, QString const& message, bool low_confidence, quint8 modifiers); }; diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp index ba034b0e2..7e74342c0 100644 --- a/UDPExamples/MessageAggregatorMainWindow.cpp +++ b/UDPExamples/MessageAggregatorMainWindow.cpp @@ -184,13 +184,16 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () connect (server_, &MessageServer::client_closed, this, &MessageAggregatorMainWindow::remove_client); 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 + connect (server_, &MessageServer::decode, [this] (bool is_new, ClientKey const& key, QTime time , qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence , bool off_air) { - decodes_model_->add_decode (is_new, id, time, snr, delta_time, delta_frequency, mode, message - , low_confidence, off_air, dock_widgets_[id]->fast_mode ());}); + decodes_model_->add_decode (is_new, key, time, snr, delta_time + , delta_frequency, mode, message + , low_confidence, off_air + , dock_widgets_[key]->fast_mode ()); + }); connect (server_, &MessageServer::WSPR_decode, beacons_model_, &BeaconsModel::add_beacon_spot); connect (server_, &MessageServer::decodes_cleared, decodes_model_, &DecodesModel::decodes_cleared); connect (server_, &MessageServer::decodes_cleared, beacons_model_, &BeaconsModel::decodes_cleared); @@ -207,7 +210,8 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow () show (); } -void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time_off, QString const& dx_call +void MessageAggregatorMainWindow::log_qso (ClientKey const& /*key*/, 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 @@ -240,9 +244,9 @@ void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time log_table_view_->scrollToBottom (); } -void MessageAggregatorMainWindow::add_client (QString const& id, QString const& version, QString const& revision) +void MessageAggregatorMainWindow::add_client (ClientKey const& key, QString const& version, QString const& revision) { - auto dock = new ClientWidget {decodes_model_, beacons_model_, id, version, revision, calls_of_interest_, this}; + auto dock = new ClientWidget {decodes_model_, beacons_model_, key, version, revision, calls_of_interest_, this}; dock->setAttribute (Qt::WA_DeleteOnClose); auto view_action = dock->toggleViewAction (); view_action->setEnabled (true); @@ -262,13 +266,13 @@ void MessageAggregatorMainWindow::add_client (QString const& id, QString const& connect (dock, &ClientWidget::highlight_callsign, server_, &MessageServer::highlight_callsign); connect (dock, &ClientWidget::switch_configuration, server_, &MessageServer::switch_configuration); connect (dock, &ClientWidget::configure, server_, &MessageServer::configure); - dock_widgets_[id] = dock; - server_->replay (id); // request decodes and status + dock_widgets_[key] = dock; + server_->replay (key); // request decodes and status } -void MessageAggregatorMainWindow::remove_client (QString const& id) +void MessageAggregatorMainWindow::remove_client (ClientKey const& key) { - auto iter = dock_widgets_.find (id); + auto iter = dock_widgets_.find (key); if (iter != std::end (dock_widgets_)) { (*iter)->dispose (); @@ -287,9 +291,9 @@ MessageAggregatorMainWindow::~MessageAggregatorMainWindow () void MessageAggregatorMainWindow::change_highlighting (QString const& call, QColor const& bg, QColor const& fg , bool last_only) { - for (auto id : dock_widgets_.keys ()) + for (auto key : dock_widgets_.keys ()) { - server_->highlight_callsign (id, call, bg, fg, last_only); + server_->highlight_callsign (key, call, bg, fg, last_only); } } diff --git a/UDPExamples/MessageAggregatorMainWindow.hpp b/UDPExamples/MessageAggregatorMainWindow.hpp index 045f4e945..445a5908e 100644 --- a/UDPExamples/MessageAggregatorMainWindow.hpp +++ b/UDPExamples/MessageAggregatorMainWindow.hpp @@ -24,11 +24,13 @@ class MessageAggregatorMainWindow { Q_OBJECT; + using ClientKey = MessageServer::ClientKey; + public: MessageAggregatorMainWindow (); ~MessageAggregatorMainWindow (); - Q_SLOT void log_qso (QString const& /*id*/, QDateTime time_off, QString const& dx_call, QString const& dx_grid + Q_SLOT void log_qso (ClientKey const&, 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 , QString const& name, QDateTime time_on, QString const& operator_call @@ -36,13 +38,13 @@ public: , QString const& exchange_sent, QString const& exchange_rcvd, QString const& prop_mode); private: - void add_client (QString const& id, QString const& version, QString const& revision); - void remove_client (QString const& id); + void add_client (ClientKey const&, QString const& version, QString const& revision); + void remove_client (ClientKey const&); void change_highlighting (QString const& call, QColor const& bg = QColor {}, QColor const& fg = QColor {}, bool last_only = false); // maps client id to widgets - using ClientsDictionary = QHash; + using ClientsDictionary = QHash; ClientsDictionary dock_widgets_; QStandardItemModel * log_; diff --git a/UDPExamples/MessageServer.cpp b/UDPExamples/MessageServer.cpp index fc36aad9d..8869c4b89 100644 --- a/UDPExamples/MessageServer.cpp +++ b/UDPExamples/MessageServer.cpp @@ -83,9 +83,8 @@ public: struct Client { Client () = default; - Client (QHostAddress const& sender_address, port_type const& sender_port) - : sender_address_ {sender_address} - , sender_port_ {sender_port} + Client (port_type const& sender_port) + : sender_port_ {sender_port} , negotiated_schema_number_ {2} // not 1 because it's broken , last_activity_ {QDateTime::currentDateTime ()} { @@ -93,12 +92,11 @@ public: Client (Client const&) = default; Client& operator= (Client const&) = default; - QHostAddress sender_address_; port_type sender_port_; quint32 negotiated_schema_number_; QDateTime last_activity_; }; - QHash clients_; // maps id to Client + QHash clients_; // maps id to Client QTimer * clock_; }; @@ -171,9 +169,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s auto id = in.id (); if (OK == check_status (in)) { - if (!clients_.contains (id)) + auto client_key = ClientKey {sender, id}; + if (!clients_.contains (client_key)) { - auto& client = (clients_[id] = {sender, sender_port}); + auto& client = (clients_[client_key] = {sender_port}); QByteArray client_version; QByteArray client_revision; @@ -194,7 +193,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s << version_.toUtf8 () << revision_.toUtf8 (); if (impl::OK == check_status (hb)) { - writeDatagram (message, client.sender_address_, client.sender_port_); + writeDatagram (message, client_key.first, sender_port); } else { @@ -204,10 +203,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s // we don't care if this fails to read in >> client_version >> client_revision; } - Q_EMIT self_->client_opened (id, QString::fromUtf8 (client_version), + Q_EMIT self_->client_opened (client_key, QString::fromUtf8 (client_version), QString::fromUtf8 (client_revision)); } - clients_[id].last_activity_ = QDateTime::currentDateTime (); + clients_[client_key].last_activity_ = QDateTime::currentDateTime (); // // message format is described in NetworkMessage.hpp @@ -219,7 +218,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s break; case NetworkMessage::Clear: - Q_EMIT self_->decodes_cleared (id); + Q_EMIT self_->decodes_cleared (client_key); break; case NetworkMessage::Status: @@ -250,7 +249,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s >> fast_mode >> special_op_mode >> frequency_tolerance >> tr_period >> configuration_name; if (check_status (in) != Fail) { - Q_EMIT self_->status_update (id, f, QString::fromUtf8 (mode), QString::fromUtf8 (dx_call) + Q_EMIT self_->status_update (client_key, f, QString::fromUtf8 (mode) + , QString::fromUtf8 (dx_call) , QString::fromUtf8 (report), QString::fromUtf8 (tx_mode) , tx_enabled, transmitting, decoding, rx_df, tx_df , QString::fromUtf8 (de_call), QString::fromUtf8 (de_grid) @@ -278,7 +278,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s >> message >> low_confidence >> off_air; if (check_status (in) != Fail) { - Q_EMIT self_->decode (is_new, id, time, snr, delta_time, delta_frequency + Q_EMIT self_->decode (is_new, client_key, time, snr, delta_time, delta_frequency , QString::fromUtf8 (mode), QString::fromUtf8 (message) , low_confidence, off_air); } @@ -302,7 +302,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s >> off_air; if (check_status (in) != Fail) { - Q_EMIT self_->WSPR_decode (is_new, id, time, snr, delta_time, frequency, drift + Q_EMIT self_->WSPR_decode (is_new, client_key, time, snr, delta_time, frequency, drift , QString::fromUtf8 (callsign), QString::fromUtf8 (grid) , power, off_air); } @@ -333,8 +333,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s >> exchange_sent >> exchange_rcvd >> prop_mode; if (check_status (in) != Fail) { - Q_EMIT self_->qso_logged (id, time_off, QString::fromUtf8 (dx_call), QString::fromUtf8 (dx_grid) - , dial_frequency, QString::fromUtf8 (mode), QString::fromUtf8 (report_sent) + Q_EMIT self_->qso_logged (client_key, time_off, QString::fromUtf8 (dx_call) + , QString::fromUtf8 (dx_grid) + , dial_frequency, QString::fromUtf8 (mode) + , QString::fromUtf8 (report_sent) , QString::fromUtf8 (report_received), QString::fromUtf8 (tx_power) , QString::fromUtf8 (comments), QString::fromUtf8 (name), time_on , QString::fromUtf8 (operator_call), QString::fromUtf8 (my_call) @@ -345,8 +347,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s break; case NetworkMessage::Close: - Q_EMIT self_->client_closed (id); - clients_.remove (id); + Q_EMIT self_->client_closed (client_key); + clients_.remove (client_key); break; case NetworkMessage::LoggedADIF: @@ -355,7 +357,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s in >> ADIF; if (check_status (in) != Fail) { - Q_EMIT self_->logged_ADIF (id, ADIF); + Q_EMIT self_->logged_ADIF (client_key, ADIF); } } break; @@ -388,7 +390,7 @@ void MessageServer::impl::tick () { if (now > (*iter).last_activity_.addSecs (NetworkMessage::pulse)) { - Q_EMIT self_->clear_decodes (iter.key ()); + Q_EMIT self_->decodes_cleared (iter.key ()); Q_EMIT self_->client_closed (iter.key ()); iter = clients_.erase (iter); // safe while iterating as doesn't rehash } @@ -462,127 +464,127 @@ void MessageServer::start (port_type port, QHostAddress const& multicast_group_a } } -void MessageServer::clear_decodes (QString const& id, quint8 window) +void MessageServer::clear_decodes (ClientKey const& key, quint8 window) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Clear, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::Clear, key.second, (*iter).negotiated_schema_number_}; out << window; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::reply (QString const& id, QTime time, qint32 snr, float delta_time +void MessageServer::reply (ClientKey const& key, QTime time, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode , QString const& message_text, bool low_confidence, quint8 modifiers) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Reply, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::Reply, key.second, (*iter).negotiated_schema_number_}; out << time << snr << delta_time << delta_frequency << mode.toUtf8 () << message_text.toUtf8 () << low_confidence << modifiers; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::replay (QString const& id) +void MessageServer::replay (ClientKey const& key) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Replay, id, (*iter).negotiated_schema_number_}; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + NetworkMessage::Builder out {&message, NetworkMessage::Replay, key.second, (*iter).negotiated_schema_number_}; + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::close (QString const& id) +void MessageServer::close (ClientKey const& key) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Close, id, (*iter).negotiated_schema_number_}; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + NetworkMessage::Builder out {&message, NetworkMessage::Close, key.second, (*iter).negotiated_schema_number_}; + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::halt_tx (QString const& id, bool auto_only) +void MessageServer::halt_tx (ClientKey const& key, bool auto_only) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::HaltTx, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::HaltTx, key.second, (*iter).negotiated_schema_number_}; out << auto_only; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::free_text (QString const& id, QString const& text, bool send) +void MessageServer::free_text (ClientKey const& key, QString const& text, bool send) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::FreeText, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::FreeText, key.second, (*iter).negotiated_schema_number_}; out << text.toUtf8 () << send; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::location (QString const& id, QString const& loc) +void MessageServer::location (ClientKey const& key, QString const& loc) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Location, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::Location, key.second, (*iter).negotiated_schema_number_}; out << loc.toUtf8 (); - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::highlight_callsign (QString const& id, QString const& callsign +void MessageServer::highlight_callsign (ClientKey const& key, QString const& callsign , QColor const& bg, QColor const& fg, bool last_only) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::HighlightCallsign, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::HighlightCallsign, key.second, (*iter).negotiated_schema_number_}; out << callsign.toUtf8 () << bg << fg << last_only; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::switch_configuration (QString const& id, QString const& configuration_name) +void MessageServer::switch_configuration (ClientKey const& key, QString const& configuration_name) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::SwitchConfiguration, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::SwitchConfiguration, key.second, (*iter).negotiated_schema_number_}; out << configuration_name.toUtf8 (); - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } -void MessageServer::configure (QString const& id, QString const& mode, quint32 frequency_tolerance +void MessageServer::configure (ClientKey const& key, QString const& mode, quint32 frequency_tolerance , QString const& submode, bool fast_mode, quint32 tr_period, quint32 rx_df , QString const& dx_call, QString const& dx_grid, bool generate_messages) { - auto iter = m_->clients_.find (id); + auto iter = m_->clients_.find (key); if (iter != std::end (m_->clients_)) { QByteArray message; - NetworkMessage::Builder out {&message, NetworkMessage::Configure, id, (*iter).negotiated_schema_number_}; + NetworkMessage::Builder out {&message, NetworkMessage::Configure, key.second, (*iter).negotiated_schema_number_}; out << mode.toUtf8 () << frequency_tolerance << submode.toUtf8 () << fast_mode << tr_period << rx_df << dx_call.toUtf8 () << dx_grid.toUtf8 () << generate_messages; - m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + m_->send_message (out, message, key.first, (*iter).sender_port_); } } diff --git a/UDPExamples/MessageServer.hpp b/UDPExamples/MessageServer.hpp index 449c70f4b..8a31e7bd5 100644 --- a/UDPExamples/MessageServer.hpp +++ b/UDPExamples/MessageServer.hpp @@ -2,6 +2,7 @@ #define MESSAGE_SERVER_HPP__ #include +#include #include #include #include @@ -33,6 +34,7 @@ class UDP_EXPORT MessageServer public: using port_type = quint16; using Frequency = Radio::Frequency; + using ClientKey = QPair; MessageServer (QObject * parent = nullptr, QString const& version = QString {}, QString const& revision = QString {}); @@ -45,73 +47,72 @@ public: , QStringList const& network_interface_names = QStringList {}); // ask the client to clear one or both of the decode windows - Q_SLOT void clear_decodes (QString const& id, quint8 window = 0); + Q_SLOT void clear_decodes (ClientKey const&, quint8 window = 0); // ask the client with identification 'id' to make the same action // as a double click on the decode would // // note that the client is not obliged to take any action and only // takes any action if the decode is present and is a CQ or QRZ message - Q_SLOT void reply (QString const& id, QTime time, qint32 snr, float delta_time, quint32 delta_frequency + Q_SLOT void reply (ClientKey const&, QTime time, qint32 snr, float delta_time, quint32 delta_frequency , QString const& mode, QString const& message, bool low_confidence, quint8 modifiers); - // ask the client with identification 'id' to close down gracefully - Q_SLOT void close (QString const& id); + // ask the client to close down gracefully + Q_SLOT void close (ClientKey const&); - // ask the client with identification 'id' to replay all decodes - Q_SLOT void replay (QString const& id); + // ask the client to replay all decodes + Q_SLOT void replay (ClientKey const&); - // ask the client with identification 'id' to halt transmitting - // auto_only just disables auto Tx, otherwise halt is immediate - Q_SLOT void halt_tx (QString const& id, bool auto_only); + // ask the client to halt transmitting auto_only just disables auto + // Tx, otherwise halt is immediate + Q_SLOT void halt_tx (ClientKey const&, bool auto_only); - // ask the client with identification 'id' to set the free text - // message and optionally send it ASAP - Q_SLOT void free_text (QString const& id, QString const& text, bool send); + // ask the client to set the free text message and optionally send + // it ASAP + Q_SLOT void free_text (ClientKey const&, QString const& text, bool send); - // ask the client with identification 'id' to set the location provided - Q_SLOT void location (QString const& id, QString const& location); + // ask the client to set the location provided + Q_SLOT void location (ClientKey const&, QString const& location); - // ask the client with identification 'id' to highlight the callsign - // specified with the given colors - Q_SLOT void highlight_callsign (QString const& id, QString const& callsign + // ask the client to highlight the callsign specified with the given + // colors + Q_SLOT void highlight_callsign (ClientKey const&, QString const& callsign , QColor const& bg = QColor {}, QColor const& fg = QColor {} , bool last_only = false); - // ask the client with identification 'id' to switch to - // configuration 'configuration_name' - Q_SLOT void switch_configuration (QString const& id, QString const& configuration_name); + // ask the client to switch to configuration 'configuration_name' + Q_SLOT void switch_configuration (ClientKey const&, QString const& configuration_name); - // ask the client with identification 'id' to change configuration - Q_SLOT void configure (QString const& id, QString const& mode, quint32 frequency_tolerance + // ask the client to change configuration + Q_SLOT void configure (ClientKey const&, QString const& mode, quint32 frequency_tolerance , QString const& submode, bool fast_mode, quint32 tr_period, quint32 rx_df , QString const& dx_call, QString const& dx_grid, bool generate_messages); // the following signals are emitted when a client broadcasts the // matching message - Q_SIGNAL void client_opened (QString const& id, QString const& version, QString const& revision); - Q_SIGNAL void status_update (QString const& id, Frequency, QString const& mode, QString const& dx_call + Q_SIGNAL void client_opened (ClientKey const&, QString const& version, QString const& revision); + Q_SIGNAL void status_update (ClientKey const&, Frequency, QString const& mode, QString const& dx_call , QString const& report, QString const& tx_mode, bool tx_enabled , bool transmitting, bool decoding, quint32 rx_df, quint32 tx_df , QString const& de_call, QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& sub_mode, bool fast_mode , quint8 special_op_mode, quint32 frequency_tolerance, quint32 tr_period , QString const& configuration_name); - 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 + Q_SIGNAL void client_closed (ClientKey const&); + Q_SIGNAL void decode (bool is_new, ClientKey const&, QTime time, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode, QString const& message , bool low_confidence, bool off_air); - Q_SIGNAL void WSPR_decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time, Frequency + Q_SIGNAL void WSPR_decode (bool is_new, ClientKey const&, QTime time, qint32 snr, float delta_time, Frequency , qint32 drift, QString const& callsign, QString const& grid, qint32 power , bool off_air); - Q_SIGNAL void qso_logged (QString const& id, QDateTime time_off, QString const& dx_call, QString const& dx_grid + Q_SIGNAL void qso_logged (ClientKey const&, 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 , 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, QString const& prop_mode); - Q_SIGNAL void decodes_cleared (QString const& id); - Q_SIGNAL void logged_ADIF (QString const& id, QByteArray const& ADIF); + Q_SIGNAL void decodes_cleared (ClientKey const&); + Q_SIGNAL void logged_ADIF (ClientKey const&, QByteArray const& ADIF); // this signal is emitted when a network error occurs Q_SIGNAL void error (QString const&) const; @@ -121,4 +122,6 @@ private: pimpl m_; }; +Q_DECLARE_METATYPE (MessageServer::ClientKey); + #endif diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 2668a6021..b7620ec90 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -41,15 +41,17 @@ class Client { Q_OBJECT + using ClientKey = MessageServer::ClientKey; + public: - explicit Client (QString const& id, QObject * parent = nullptr) + explicit Client (ClientKey const& key, QObject * parent = nullptr) : QObject {parent} - , id_ {id} + , key_ {key} , dial_frequency_ {0u} { } - Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& /*dx_call*/ + Q_SLOT void update_status (ClientKey const& key, Frequency f, QString const& mode, QString const& /*dx_call*/ , QString const& /*report*/, QString const& /*tx_mode*/, bool /*tx_enabled*/ , bool /*transmitting*/, bool /*decoding*/, qint32 /*rx_df*/, qint32 /*tx_df*/ , QString const& /*de_call*/, QString const& /*de_grid*/, QString const& /*dx_grid*/ @@ -57,67 +59,73 @@ public: , quint8 /*special_op_mode*/, quint32 /*frequency_tolerance*/, quint32 /*tr_period*/ , QString const& /*configuration_name*/) { - if (id == id_) + if (key == key_) { if (f != dial_frequency_) { - std::cout << tr ("%1: Dial frequency changed to %2").arg (id_).arg (f).toStdString () << std::endl; + std::cout << tr ("%1(%2): Dial frequency changed to %3") + .arg (key_.second).arg (key_.first.toString ()).arg (f).toStdString () << std::endl; dial_frequency_ = f; } if (mode + sub_mode != mode_) { - std::cout << tr ("%1: Mode changed to %2").arg (id_).arg (mode + sub_mode).toStdString () << std::endl; + std::cout << tr ("%1(%2): Mode changed to %3") + .arg (key_.second).arg (key_.first.toString ()).arg (mode + sub_mode).toStdString () << std::endl; mode_ = mode + sub_mode; } } } - Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime time, qint32 snr + Q_SLOT void decode_added (bool is_new, ClientKey const& key, QTime time, qint32 snr , float delta_time, quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence, bool off_air) { - if (client_id == id_) + if (key == key_) { qDebug () << "new:" << is_new << "t:" << time << "snr:" << snr << "Dt:" << delta_time << "Df:" << delta_frequency << "mode:" << mode << "Confidence:" << (low_confidence ? "low" : "high") << "On air:" << !off_air; - std::cout << tr ("%1: Decoded %2").arg (id_).arg (message).toStdString () << std::endl; + std::cout << tr ("%1(%2): Decoded %3") + .arg (key_.second).arg (key_.first.toString ()).arg (message).toStdString () << std::endl; } } - Q_SLOT void beacon_spot_added (bool is_new, QString const& client_id, QTime time, qint32 snr + Q_SLOT void beacon_spot_added (bool is_new, ClientKey const& key, QTime time, qint32 snr , float delta_time, Frequency delta_frequency, qint32 drift, QString const& callsign , QString const& grid, qint32 power, bool off_air) { - if (client_id == id_) + if (key == key_) { qDebug () << "new:" << is_new << "t:" << time << "snr:" << snr << "Dt:" << delta_time << "Df:" << delta_frequency << "drift:" << drift; - std::cout << tr ("%1: WSPR decode %2 grid %3 power: %4").arg (id_).arg (callsign).arg (grid).arg (power).toStdString () + std::cout << tr ("%1(%2): WSPR decode %3 grid %4 power: %5") + .arg (key_.second).arg (key_.first.toString ()).arg (callsign).arg (grid).arg (power).toStdString () << "On air:" << !off_air << std::endl; } } - Q_SLOT void qso_logged (QString const&client_id, QDateTime time_off, QString const& dx_call, QString const& dx_grid + Q_SLOT void qso_logged (ClientKey const& key, 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, 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, QString const& prop_mode) { - if (client_id == id_) + if (key == key_) { - qDebug () << "time_on:" << time_on << "time_off:" << time_off << "dx_call:" << dx_call << "grid:" << dx_grid + qDebug () << "time_on:" << time_on << "time_off:" << time_off << "dx_call:" + << dx_call << "grid:" << dx_grid << "freq:" << dial_frequency << "mode:" << mode << "rpt_sent:" << report_sent << "rpt_rcvd:" << report_received << "Tx_pwr:" << tx_power << "comments:" << comments << "name:" << name << "operator_call:" << operator_call << "my_call:" << my_call << "my_grid:" << my_grid << "exchange_sent:" << exchange_sent << "exchange_rcvd:" << exchange_rcvd << "prop_mode:" << prop_mode; std::cout << QByteArray {80, '-'}.data () << '\n'; - std::cout << tr ("%1: Logged %2 grid: %3 power: %4 sent: %5 recd: %6 freq: %7 time_off: %8 op: %9 my_call: %10 my_grid: %11 exchange_sent: %12 exchange_rcvd: %13 comments: %14 prop_mode: %15") - .arg (id_).arg (dx_call).arg (dx_grid).arg (tx_power).arg (report_sent).arg (report_received) + std::cout << tr ("%1(%2): Logged %3 grid: %4 power: %5 sent: %6 recd: %7 freq: %8 time_off: %9 op: %10 my_call: %11 my_grid: %12 exchange_sent: %13 exchange_rcvd: %14 comments: %15 prop_mode: %16") + .arg (key_.second).arg (key.first.toString ()).arg (dx_call).arg (dx_grid).arg (tx_power) + .arg (report_sent).arg (report_received) .arg (dial_frequency).arg (time_off.toString("yyyy-MM-dd hh:mm:ss.z")).arg (operator_call) .arg (my_call).arg (my_grid).arg (exchange_sent).arg (exchange_rcvd) .arg (comments).arg (prop_mode).toStdString () @@ -125,9 +133,9 @@ public: } } - Q_SLOT void logged_ADIF (QString const&client_id, QByteArray const& ADIF) + Q_SLOT void logged_ADIF (ClientKey const& key, QByteArray const& ADIF) { - if (client_id == id_) + if (key == key_) { qDebug () << "ADIF:" << ADIF; std::cout << QByteArray {80, '-'}.data () << '\n'; @@ -136,7 +144,7 @@ public: } private: - QString id_; + ClientKey key_; Frequency dial_frequency_; QString mode_; }; @@ -146,6 +154,8 @@ class Server { Q_OBJECT + using ClientKey = MessageServer::ClientKey; + public: Server (port_type port, QHostAddress const& multicast_group, QStringList const& network_interface_names) : server_ {new MessageServer {this}} @@ -161,17 +171,18 @@ public: } private: - void add_client (QString const& id, QString const& version, QString const& revision) + void add_client (ClientKey const& key, QString const& version, QString const& revision) { - auto client = new Client {id}; + auto client = new Client {key}; connect (server_, &MessageServer::status_update, client, &Client::update_status); connect (server_, &MessageServer::decode, client, &Client::decode_added); connect (server_, &MessageServer::WSPR_decode, client, &Client::beacon_spot_added); connect (server_, &MessageServer::qso_logged, client, &Client::qso_logged); connect (server_, &MessageServer::logged_ADIF, client, &Client::logged_ADIF); - clients_[id] = client; - server_->replay (id); - std::cout << "Discovered WSJT-X instance: " << id.toStdString (); + clients_[key] = client; + server_->replay (key); + std::cout << "Discovered WSJT-X instance: " << key.second.toStdString () + << '(' << key.first.toString ().toStdString () << ')'; if (version.size ()) { std::cout << " v" << version.toStdString (); @@ -183,21 +194,22 @@ private: std::cout << std::endl; } - void remove_client (QString const& id) + void remove_client (ClientKey const& key) { - auto iter = clients_.find (id); + auto iter = clients_.find (key); if (iter != std::end (clients_)) { clients_.erase (iter); (*iter)->deleteLater (); } - std::cout << "Removed WSJT-X instance: " << id.toStdString () << std::endl; + std::cout << "Removed WSJT-X instance: " << key.second.toStdString () + << '(' << key.first.toString ().toStdString () << ')' << std::endl; } MessageServer * server_; - // maps client id to clients - QHash clients_; + // maps client key to clients + QHash clients_; }; #include "UDPDaemon.moc"