diff --git a/MessageClient.cpp b/MessageClient.cpp index 6e2ea7955..0629c3026 100644 --- a/MessageClient.cpp +++ b/MessageClient.cpp @@ -261,6 +261,18 @@ void MessageClient::impl::parse_message (QByteArray const& msg) } break; + case NetworkMessage::SwitchConfiguration: + { + QByteArray configuration_name; + in >> configuration_name; + TRACE_UDP ("SwitchConfiguration name:" << configuration_name); + if (check_status (in) != Fail && configuration_name.size ()) + { + Q_EMIT self_->switch_configuration (QString::fromUtf8 (configuration_name)); + } + } + break; + default: // Ignore // @@ -444,7 +456,8 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con , qint32 rx_df, qint32 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) + , bool fast_mode, quint8 special_op_mode + , QString const& configuration_name) { if (m_->server_port_ && !m_->server_string_.isEmpty ()) { @@ -453,8 +466,8 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con out << f << mode.toUtf8 () << dx_call.toUtf8 () << report.toUtf8 () << tx_mode.toUtf8 () << tx_enabled << transmitting << decoding << rx_df << tx_df << de_call.toUtf8 () << de_grid.toUtf8 () << dx_grid.toUtf8 () << watchdog_timeout << sub_mode.toUtf8 () - << fast_mode << special_op_mode; - TRACE_UDP ("frequency:" << f << "mode:" << mode << "DX:" << dx_call << "report:" << report << "Tx mode:" << tx_mode << "tx_enabled:" << tx_enabled << "Tx:" << transmitting << "decoding:" << decoding << "Rx df:" << rx_df << "Tx df:" << tx_df << "DE:" << de_call << "DE grid:" << de_grid << "DX grid:" << dx_grid << "w/d t/o:" << watchdog_timeout << "sub_mode:" << sub_mode << "fast mode:" << fast_mode << "spec op mode:" << special_op_mode); + << fast_mode << special_op_mode << configuration_name.toUtf8 (); + TRACE_UDP ("frequency:" << f << "mode:" << mode << "DX:" << dx_call << "report:" << report << "Tx mode:" << tx_mode << "tx_enabled:" << tx_enabled << "Tx:" << transmitting << "decoding:" << decoding << "Rx df:" << rx_df << "Tx df:" << tx_df << "DE:" << de_call << "DE grid:" << de_grid << "DX grid:" << dx_grid << "w/d t/o:" << watchdog_timeout << "sub_mode:" << sub_mode << "fast mode:" << fast_mode << "spec op mode:" << special_op_mode << "configuration name:" << configuration_name); m_->send_message (out, message); } } diff --git a/MessageClient.hpp b/MessageClient.hpp index ca5f02037..2396a6ad0 100644 --- a/MessageClient.hpp +++ b/MessageClient.hpp @@ -52,7 +52,7 @@ public: , 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, bool watchdog_timeout, QString const& sub_mode - , bool fast_mode, quint8 special_op_mode); + , bool fast_mode, quint8 special_op_mode, QString const& configuration_name); Q_SLOT void decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency , QString const& mode, QString const& message, bool low_confidence , bool off_air); @@ -105,6 +105,10 @@ public: // callsign request for the specified call Q_SIGNAL void highlight_callsign (QString const& callsign, QColor const& bg, QColor const& fg, bool last_only); + // this signal is emitted if the server has requested a switch to a + // new configuration + Q_SIGNAL void switch_configuration (QString const& configuration_name); + // this signal is emitted when network errors occur or if a host // lookup fails Q_SIGNAL void error (QString const&) const; diff --git a/MessageServer.cpp b/MessageServer.cpp index dadf3d984..02d23e460 100644 --- a/MessageServer.cpp +++ b/MessageServer.cpp @@ -247,9 +247,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s QByteArray sub_mode; bool fast_mode {false}; quint8 special_op_mode {0}; + QByteArray configuration_name; in >> f >> mode >> dx_call >> report >> tx_mode >> tx_enabled >> transmitting >> decoding >> rx_df >> tx_df >> de_call >> de_grid >> dx_grid >> watchdog_timeout >> sub_mode - >> fast_mode >> special_op_mode; + >> fast_mode >> special_op_mode >> configuration_name; if (check_status (in) != Fail) { Q_EMIT self_->status_update (id, f, QString::fromUtf8 (mode), QString::fromUtf8 (dx_call) @@ -258,7 +259,7 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s , QString::fromUtf8 (de_call), QString::fromUtf8 (de_grid) , QString::fromUtf8 (dx_grid), watchdog_timeout , QString::fromUtf8 (sub_mode), fast_mode - , special_op_mode); + , special_op_mode, QString::fromUtf8 (configuration_name)); } } break; @@ -541,3 +542,15 @@ void MessageServer::highlight_callsign (QString const& id, QString const& callsi m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); } } + +void MessageServer::switch_configuration (QString const& id, QString const& configuration_name) +{ + auto iter = m_->clients_.find (id); + if (iter != std::end (m_->clients_)) + { + QByteArray message; + NetworkMessage::Builder out {&message, NetworkMessage::SwitchConfiguration, id, (*iter).negotiated_schema_number_}; + out << configuration_name.toUtf8 (); + m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_); + } +} diff --git a/MessageServer.hpp b/MessageServer.hpp index 12377bef9..2764889cf 100644 --- a/MessageServer.hpp +++ b/MessageServer.hpp @@ -72,6 +72,9 @@ public: , QColor const& bg = QColor {}, QColor const& fg = QColor {} , bool last_only = false); + // ask the client with identification 'id' to switch configuration + Q_SLOT void switch_configuration (QString const& id, QString const& configuration_name); + // 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); @@ -80,7 +83,7 @@ public: , bool transmitting, bool decoding, qint32 rx_df, qint32 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); + , quint8 special_op_mode, 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 , quint32 delta_frequency, QString const& mode, QString const& message diff --git a/MultiSettings.cpp b/MultiSettings.cpp index c0db0ed67..29c686d3d 100644 --- a/MultiSettings.cpp +++ b/MultiSettings.cpp @@ -159,13 +159,16 @@ public: bool exit (); QSettings settings_; + QString current_; + + // switch to this configuration + void select_configuration (QString const& target_name); private: using Dictionary = QMap; // create a configuration maintenance sub menu - QMenu * create_sub_menu (QMainWindow * main_window, - QMenu * parent, + QMenu * create_sub_menu (QMenu * parent, QString const& menu_title, QActionGroup * = nullptr); @@ -175,32 +178,32 @@ private: // write the settings values from the dictionary to the current group void load_from (Dictionary const&, bool add_placeholder = true); - // switch to this configuration - void select_configuration (QMainWindow *, QMenu const *); - // clone this configuration - void clone_configuration (QMainWindow * main_window, QMenu *, QMenu const *); + void clone_configuration (QMenu *, QMenu const *); // update this configuration from another - void clone_into_configuration (QMainWindow *, QMenu const *); + void clone_into_configuration (QMenu const *); // reset configuration to default values - void reset_configuration (QMainWindow *, QMenu const *); + void reset_configuration (QMenu const *); // change configuration name - void rename_configuration (QMainWindow *, QMenu *); + void rename_configuration (QMenu *); // remove a configuration - void delete_configuration (QMainWindow *, QMenu *); + void delete_configuration (QMenu *); + + // action to take on restart + enum class RepositionType {unchanged, replace, save_and_replace}; + void restart (RepositionType); MultiSettings const * parent_; // required for emitting signals + QMainWindow * main_window_; bool name_change_emit_pending_; // delayed until menu built QFont original_font_; - QString current_; - // action to take on restart - enum class RepositionType {unchanged, replace, save_and_replace} reposition_type_; + RepositionType reposition_type_; Dictionary new_settings_; bool exit_flag_; // false means loop around with new // configuration @@ -267,6 +270,16 @@ void MultiSettings::create_menu_actions (QMainWindow * main_window, QMenu * menu m_->create_menu_actions (main_window, menu); } +void MultiSettings::select_configuration (QString const& name) +{ + m_->select_configuration (name); +} + +QString MultiSettings::configuration_name () const +{ + return m_->current_; +} + bool MultiSettings::exit () { return m_->exit (); @@ -275,6 +288,7 @@ bool MultiSettings::exit () MultiSettings::impl::impl (MultiSettings const * parent, QString const& config_name) : settings_ {settings_path (), QSettings::IniFormat} , parent_ {parent} + , main_window_ {nullptr} , name_change_emit_pending_ {true} , reposition_type_ {RepositionType::unchanged} , exit_flag_ {true} @@ -411,13 +425,14 @@ bool MultiSettings::impl::reposition () // and, reset void MultiSettings::impl::create_menu_actions (QMainWindow * main_window, QMenu * menu) { + main_window_ = main_window; auto const& current_group = settings_.group (); if (current_group.size ()) settings_.endGroup (); SettingsGroup alternatives {&settings_, multi_settings_root_group}; // get the current configuration name auto const& current_configuration_name = settings_.value (multi_settings_current_name_key, tr (default_string)).toString (); // add the default configuration sub menu - QMenu * default_menu = create_sub_menu (main_window, menu, current_configuration_name, configurations_group_); + QMenu * default_menu = create_sub_menu (menu, current_configuration_name, configurations_group_); // and set as the current configuration default_menu->menuAction ()->setChecked (true); @@ -427,7 +442,7 @@ void MultiSettings::impl::create_menu_actions (QMainWindow * main_window, QMenu // add all the other configurations for (auto const& configuration_name: available_configurations) { - create_sub_menu (main_window, menu, configuration_name, configurations_group_); + create_sub_menu (menu, configuration_name, configurations_group_); } if (current_group.size ()) settings_.beginGroup (current_group); @@ -450,8 +465,7 @@ bool MultiSettings::impl::exit () return reposition (); } -QMenu * MultiSettings::impl::create_sub_menu (QMainWindow * main_window, - QMenu * parent_menu, +QMenu * MultiSettings::impl::create_sub_menu (QMenu * parent_menu, QString const& menu_title, QActionGroup * action_group) { @@ -460,7 +474,7 @@ QMenu * MultiSettings::impl::create_sub_menu (QMainWindow * main_window, sub_menu->menuAction ()->setCheckable (true); // populate sub-menu actions before showing - connect (sub_menu, &QMenu::aboutToShow, [this, main_window, parent_menu, sub_menu] () { + connect (sub_menu, &QMenu::aboutToShow, [this, parent_menu, sub_menu] () { // depopulate before populating and showing because on Mac OS X // there is an issue with depopulating in QMenu::aboutToHide() // with connections being disconnected before they are actioned @@ -474,16 +488,16 @@ QMenu * MultiSettings::impl::create_sub_menu (QMainWindow * main_window, { auto select_action = new QAction {tr ("&Switch To"), this}; sub_menu->addAction (select_action); - connect (select_action, &QAction::triggered, [this, main_window, sub_menu] (bool) { - select_configuration (main_window, sub_menu); + connect (select_action, &QAction::triggered, [this, sub_menu] (bool) { + select_configuration (sub_menu->title ()); }); sub_menu->addSeparator (); } auto clone_action = new QAction {tr ("&Clone"), this}; sub_menu->addAction (clone_action); - connect (clone_action, &QAction::triggered, [this, main_window, parent_menu, sub_menu] (bool) { - clone_configuration (main_window, parent_menu, sub_menu); + connect (clone_action, &QAction::triggered, [this, parent_menu, sub_menu] (bool) { + clone_configuration (parent_menu, sub_menu); }); auto const& current_group = settings_.group (); @@ -493,29 +507,29 @@ QMenu * MultiSettings::impl::create_sub_menu (QMainWindow * main_window, { auto clone_into_action = new QAction {tr ("Clone &Into ..."), this}; sub_menu->addAction (clone_into_action); - connect (clone_into_action, &QAction::triggered, [this, main_window, sub_menu] (bool) { - clone_into_configuration (main_window, sub_menu); + connect (clone_into_action, &QAction::triggered, [this, sub_menu] (bool) { + clone_into_configuration (sub_menu); }); } if (current_group.size ()) settings_.beginGroup (current_group); auto reset_action = new QAction {tr ("R&eset"), this}; sub_menu->addAction (reset_action); - connect (reset_action, &QAction::triggered, [this, main_window, sub_menu] (bool) { - reset_configuration (main_window, sub_menu); + connect (reset_action, &QAction::triggered, [this, sub_menu] (bool) { + reset_configuration (sub_menu); }); auto rename_action = new QAction {tr ("&Rename ..."), this}; sub_menu->addAction (rename_action); - connect (rename_action, &QAction::triggered, [this, main_window, sub_menu] (bool) { - rename_configuration (main_window, sub_menu); + connect (rename_action, &QAction::triggered, [this, sub_menu] (bool) { + rename_configuration (sub_menu); }); if (!is_current) { auto delete_action = new QAction {tr ("&Delete"), this}; sub_menu->addAction (delete_action); - connect (delete_action, &QAction::triggered, [this, main_window, sub_menu] (bool) { - delete_configuration (main_window, sub_menu); + connect (delete_action, &QAction::triggered, [this, sub_menu] (bool) { + delete_configuration (sub_menu); }); } }); @@ -558,11 +572,9 @@ void MultiSettings::impl::load_from (Dictionary const& dictionary, bool add_plac settings_.sync (); } -void MultiSettings::impl::select_configuration (QMainWindow * main_window, QMenu const * menu) +void MultiSettings::impl::select_configuration (QString const& target_name) { - auto const& target_name = menu->title (); - - if (target_name != current_) + if (main_window_ && target_name != current_) { { auto const& current_group = settings_.group (); @@ -577,13 +589,11 @@ void MultiSettings::impl::select_configuration (QMainWindow * main_window, QMenu // and set up the restart current_ = target_name; Q_EMIT parent_->configurationNameChanged (unescape_ampersands (current_)); - reposition_type_ = RepositionType::save_and_replace; - exit_flag_ = false; - main_window->close (); + restart (RepositionType::save_and_replace); } } -void MultiSettings::impl::clone_configuration (QMainWindow * main_window, QMenu * parent_menu, QMenu const * menu) +void MultiSettings::impl::clone_configuration (QMenu * parent_menu, QMenu const * menu) { auto const& current_group = settings_.group (); if (current_group.size ()) settings_.endGroup (); @@ -616,12 +626,15 @@ void MultiSettings::impl::clone_configuration (QMainWindow * main_window, QMenu load_from (source_settings); // insert the new configuration sub menu in the parent menu - create_sub_menu (main_window, parent_menu, new_name, configurations_group_); + create_sub_menu (parent_menu, new_name, configurations_group_); if (current_group.size ()) settings_.beginGroup (current_group); } -void MultiSettings::impl::clone_into_configuration (QMainWindow * main_window, QMenu const * menu) +void MultiSettings::impl::clone_into_configuration (QMenu const * menu) { + Q_ASSERT (main_window_); + if (!main_window_) return; + auto const& current_group = settings_.group (); if (current_group.size ()) settings_.endGroup (); auto const& target_name = menu->title (); @@ -642,15 +655,16 @@ void MultiSettings::impl::clone_into_configuration (QMainWindow * main_window, Q } // pick a source configuration - ExistingNameDialog dialog {sources, main_window}; + ExistingNameDialog dialog {sources, main_window_}; if (sources.size () && (1 == sources.size () || QDialog::Accepted == dialog.exec ())) { QString source_name {1 == sources.size () ? sources.at (0) : dialog.name ()}; - if (MessageBox::Yes == MessageBox::query_message (main_window, - tr ("Clone Into Configuration"), - tr ("Confirm overwrite of all values for configuration \"%1\" with values from \"%2\"?") - .arg (unescape_ampersands (target_name)) - .arg (unescape_ampersands (source_name)))) + if (main_window_ + && MessageBox::Yes == MessageBox::query_message (main_window_, + tr ("Clone Into Configuration"), + tr ("Confirm overwrite of all values for configuration \"%1\" with values from \"%2\"?") + .arg (unescape_ampersands (target_name)) + .arg (unescape_ampersands (source_name)))) { // grab the data to clone from if (source_name == current_group_name) @@ -669,9 +683,7 @@ void MultiSettings::impl::clone_into_configuration (QMainWindow * main_window, Q if (target_name == current_) { // restart with new settings - reposition_type_ = RepositionType::replace; - exit_flag_ = false; - main_window->close (); + restart (RepositionType::replace); } else { @@ -686,14 +698,18 @@ void MultiSettings::impl::clone_into_configuration (QMainWindow * main_window, Q if (current_group.size ()) settings_.beginGroup (current_group); } -void MultiSettings::impl::reset_configuration (QMainWindow * main_window, QMenu const * menu) +void MultiSettings::impl::reset_configuration (QMenu const * menu) { + Q_ASSERT (main_window_); + if (!main_window_) return; + auto const& target_name = menu->title (); - if (MessageBox::Yes != MessageBox::query_message (main_window, - tr ("Reset Configuration"), - tr ("Confirm reset to default values for configuration \"%1\"?") - .arg (unescape_ampersands (target_name)))) + if (!main_window_ + || MessageBox::Yes != MessageBox::query_message (main_window_, + tr ("Reset Configuration"), + tr ("Confirm reset to default values for configuration \"%1\"?") + .arg (unescape_ampersands (target_name)))) { return; } @@ -701,10 +717,8 @@ void MultiSettings::impl::reset_configuration (QMainWindow * main_window, QMenu if (target_name == current_) { // restart with default settings - reposition_type_ = RepositionType::replace; new_settings_.clear (); - exit_flag_ = false; - main_window->close (); + restart (RepositionType::replace); } else { @@ -721,8 +735,11 @@ void MultiSettings::impl::reset_configuration (QMainWindow * main_window, QMenu } } -void MultiSettings::impl::rename_configuration (QMainWindow * main_window, QMenu * menu) +void MultiSettings::impl::rename_configuration (QMenu * menu) { + Q_ASSERT (main_window_); + if (!main_window_) return; + auto const& current_group = settings_.group (); if (current_group.size ()) settings_.endGroup (); auto const& target_name = menu->title (); @@ -733,7 +750,7 @@ void MultiSettings::impl::rename_configuration (QMainWindow * main_window, QMenu invalid_names << settings_.value (multi_settings_current_name_key).toString (); // get the new name - NameDialog dialog {target_name, invalid_names, main_window}; + NameDialog dialog {target_name, invalid_names, main_window_}; if (QDialog::Accepted == dialog.exec ()) { if (target_name == current_) @@ -764,8 +781,9 @@ void MultiSettings::impl::rename_configuration (QMainWindow * main_window, QMenu if (current_group.size ()) settings_.beginGroup (current_group); } -void MultiSettings::impl::delete_configuration (QMainWindow * main_window, QMenu * menu) +void MultiSettings::impl::delete_configuration (QMenu * menu) { + Q_ASSERT (main_window_); auto const& target_name = menu->title (); if (target_name == current_) @@ -774,10 +792,11 @@ void MultiSettings::impl::delete_configuration (QMainWindow * main_window, QMenu } else { - if (MessageBox::Yes != MessageBox::query_message (main_window, - tr ("Delete Configuration"), - tr ("Confirm deletion of configuration \"%1\"?") - .arg (unescape_ampersands (target_name)))) + if (!main_window_ + || MessageBox::Yes != MessageBox::query_message (main_window_, + tr ("Delete Configuration"), + tr ("Confirm deletion of configuration \"%1\"?") + .arg (unescape_ampersands (target_name)))) { return; } @@ -793,3 +812,12 @@ void MultiSettings::impl::delete_configuration (QMainWindow * main_window, QMenu // update the menu menu->deleteLater (); } + +void MultiSettings::impl::restart (RepositionType type) +{ + Q_ASSERT (main_window_); + reposition_type_ = type; + exit_flag_ = false; + main_window_->close (); + main_window_ = nullptr; +} diff --git a/MultiSettings.hpp b/MultiSettings.hpp index 051553b48..5e0c9a679 100644 --- a/MultiSettings.hpp +++ b/MultiSettings.hpp @@ -80,6 +80,10 @@ public: // action is triggered. void create_menu_actions (QMainWindow *, QMenu *); + // switch to this configuration if it exists + Q_SLOT void select_configuration (QString const& name); + QString configuration_name () const; + // Access to the QSettings object instance. QSettings * settings (); diff --git a/NetworkMessage.hpp b/NetworkMessage.hpp index 4783bb369..be85d63ee 100644 --- a/NetworkMessage.hpp +++ b/NetworkMessage.hpp @@ -124,7 +124,8 @@ * Tx Watchdog bool * Sub-mode utf8 * Fast mode bool - * Special operation mode quint8 + * Special Operation Mode quint8 + * Configuration Name utf8 * * WSJT-X sends this status message when various internal state * changes to allow the server to track the relevant state of each @@ -145,7 +146,8 @@ * When the Tx DF changes, * When settings are exited, * When the DX call or grid changes, - * When the Tx watchdog is set or reset. + * When the Tx watchdog is set or reset, + * When the configuration name changes. * * The Special operation mode is an enumeration that indicates the * setting selected in the WSJT-X "Settings->Advanced->Special @@ -414,6 +416,15 @@ * the last instance only instead of all instances of the * specified call be highlighted or have it's highlighting * cleared. + * + * + * Switch Configuration In 14 quint32 + * Id (unique key) utf8 + * Configuration Name utf8 + * + * The server may send this message at any time. The message + * specifies the name of the configuration to switch to. The new + * configuration must exist. */ #include @@ -443,6 +454,7 @@ namespace NetworkMessage Location, LoggedADIF, HighlightCallsign, + SwitchConfiguration, maximum_message_type_ // ONLY add new message types // immediately before here }; diff --git a/UDPExamples/ClientWidget.cpp b/UDPExamples/ClientWidget.cpp index 1715670bf..7d1601938 100644 --- a/UDPExamples/ClientWidget.cpp +++ b/UDPExamples/ClientWidget.cpp @@ -139,6 +139,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod , rx_df_label_ {new QLabel} , tx_df_label_ {new QLabel} , report_label_ {new QLabel} + , configuration_line_edit_ {new QLineEdit} , columns_resized_ {false} { // set up widgets @@ -155,6 +156,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod auto form_layout = new QFormLayout; form_layout->addRow (tr ("Free text:"), message_line_edit_); form_layout->addRow (tr ("Temporary grid:"), grid_line_edit_); + form_layout->addRow (tr ("Configuration name:"), configuration_line_edit_); message_line_edit_->setValidator (new QRegExpValidator {message_alphabet, this}); grid_line_edit_->setValidator (new MaidenheadLocatorValidator {this}); connect (message_line_edit_, &QLineEdit::textEdited, [this] (QString const& text) { @@ -166,6 +168,9 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod connect (grid_line_edit_, &QLineEdit::editingFinished, [this] () { Q_EMIT location (id_, grid_line_edit_->text ()); }); + connect (configuration_line_edit_, &QLineEdit::editingFinished, [this] () { + Q_EMIT switch_configuration (id_, configuration_line_edit_->text ()); + }); auto decodes_page = new QWidget; auto decodes_layout = new QVBoxLayout {decodes_page}; @@ -266,7 +271,7 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const& , bool transmitting, bool decoding, qint32 rx_df, qint32 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) + , quint8 special_op_mode, QString const& configuration_name) { if (id == id_) { @@ -304,6 +309,10 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const& halt_tx_button_->setEnabled (transmitting); update_dynamic_property (mode_label_, "decoding", decoding); update_dynamic_property (tx_df_label_, "watchdog_timeout", watchdog_timeout); + if (!configuration_line_edit_->hasFocus ()) + { + configuration_line_edit_->setText (configuration_name); + } } } diff --git a/UDPExamples/ClientWidget.hpp b/UDPExamples/ClientWidget.hpp index 22488531c..9aa8d35a0 100644 --- a/UDPExamples/ClientWidget.hpp +++ b/UDPExamples/ClientWidget.hpp @@ -34,7 +34,7 @@ public: , bool transmitting, bool decoding, qint32 rx_df, qint32 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); + , quint8 special_op_mode, QString const& configuration_name); Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime, qint32 snr , float delta_time, quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence, bool off_air); @@ -52,8 +52,10 @@ public: Q_SIGNAL void highlight_callsign (QString const& id, 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); private: + QString id_; QListWidget const * calls_of_interest_; class IdFilterModel final @@ -94,6 +96,7 @@ private: QLabel * rx_df_label_; QLabel * tx_df_label_; QLabel * report_label_; + QLineEdit * configuration_line_edit_; bool columns_resized_; }; diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp index e6937e6cb..34c674f2c 100644 --- a/UDPExamples/MessageAggregatorMainWindow.cpp +++ b/UDPExamples/MessageAggregatorMainWindow.cpp @@ -256,6 +256,7 @@ void MessageAggregatorMainWindow::add_client (QString const& id, QString const& connect (dock, &ClientWidget::location, server_, &MessageServer::location); connect (view_action, &QAction::toggled, dock, &ClientWidget::setVisible); connect (dock, &ClientWidget::highlight_callsign, server_, &MessageServer::highlight_callsign); + connect (dock, &ClientWidget::switch_configuration, server_, &MessageServer::switch_configuration); dock_widgets_[id] = dock; server_->replay (id); // request decodes and status } diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index 0ee202dc7..98ff49e6e 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -51,7 +51,7 @@ public: , bool /*transmitting*/, bool /*decoding*/, qint32 /*rx_df*/, qint32 /*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*/) + , quint8 /*special_op_mode*/, QString const& /*configuration_name*/) { if (id == id_) { diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 0d6d63e74..529dab19d 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -560,6 +560,8 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, connect (m_messageClient, &MessageClient::highlight_callsign, ui->decodedTextBrowser, &DisplayText::highlight_callsign); + connect (m_messageClient, &MessageClient::switch_configuration, m_multi_settings, &MultiSettings::select_configuration); + // Hook up WSPR band hopping connect (ui->band_hopping_schedule_push_button, &QPushButton::clicked , &m_WSPR_band_hopping, &WSPRBandHopping::show_dialog); @@ -719,6 +721,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple, else { config_label.hide (); } + statusUpdate (); }); m_multi_settings->create_menu_actions (this, ui->menuConfig); m_configurations_button = m_rigErrorMessageBox.addButton (tr ("Configurations...") @@ -7908,7 +7911,8 @@ void MainWindow::statusUpdate () const m_config.my_callsign (), m_config.my_grid (), m_hisGrid, m_tx_watchdog, submode != QChar::Null ? QString {submode} : QString {}, m_bFastMode, - static_cast (m_config.special_op_id ())); + static_cast (m_config.special_op_id ()), + m_multi_settings->configuration_name ()); } void MainWindow::childEvent (QChildEvent * e)