#include "TestConfiguration.hpp" #include #include #include #include #include #include #include #include #include #include #include "Bands.hpp" #include "FrequencyList.hpp" #include "Configuration.hpp" #include "LiveFrequencyValidator.hpp" #include "pimpl_impl.hpp" #include "ui_TestConfiguration.h" namespace { char const * const title = "Configuration Test v" WSJTX_STRINGIZE (CONFIG_TEST_VERSION_MAJOR) "." WSJTX_STRINGIZE (CONFIG_TEST_VERSION_MINOR) "." WSJTX_STRINGIZE (CONFIG_TEST_VERSION_PATCH) ", " WSJTX_STRINGIZE (SVNVERSION); // these undocumented flag values when stored in (Qt::UserRole - 1) // of a ComboBox item model index allow the item to be enabled or // disabled int const combo_box_item_enabled (32 | 1); int const combo_box_item_disabled (0); auto LCD_error = "-- Error --"; } class status_bar_frequency final : public QLabel { public: status_bar_frequency (QString const& prefix, QWidget * parent = 0) : QLabel {parent} , prefix_ {prefix} { } void setText (QString const& text) { QLabel::setText (prefix_ + " Frequency: " + text); } private: QString prefix_; }; class TestConfiguration::impl final : public QMainWindow { Q_OBJECT; public: using Frequency = Radio::Frequency; explicit impl (QString const& instance_key, QSettings *, QWidget * parent = nullptr); void closeEvent (QCloseEvent *) override; Q_SIGNAL void new_frequency (Frequency) const; Q_SIGNAL void new_tx_frequency (Frequency = 0, bool rationalise_mode = true) const; private: Q_SLOT void on_configuration_action_triggered (); Q_SLOT void on_band_combo_box_activated (int); Q_SLOT void on_mode_combo_box_activated (int); Q_SLOT void on_PTT_push_button_clicked (bool); Q_SLOT void on_split_push_button_clicked (bool); Q_SLOT void on_TX_offset_spin_box_valueChanged (int); Q_SLOT void on_sync_push_button_clicked (bool); Q_SLOT void handle_transceiver_update (Transceiver::TransceiverState); Q_SLOT void handle_transceiver_failure (QString); void information_message_box (QString const& reason, QString const& detail); void read_settings (); void write_settings (); void load_models (); void sync_rig (); void band_changed (Frequency); void frequency_changed (Frequency); Ui::test_configuration_main_window * ui_; QSettings * settings_; QString callsign_; Configuration configuration_dialog_; bool updating_models_; // hold off UI reaction while adjusting models bool band_edited_; Transceiver::TransceiverState rig_state_; Frequency desired_frequency_; status_bar_frequency RX_frequency_; status_bar_frequency TX_frequency_; }; #include "TestConfiguration.moc" TestConfiguration::TestConfiguration (QString const& instance_key, QSettings * settings, QWidget * parent) : m_ {instance_key, settings, parent} { } TestConfiguration::~TestConfiguration () { } TestConfiguration::impl::impl (QString const& instance_key, QSettings * settings, QWidget * parent) : QMainWindow {parent} , ui_ {new Ui::test_configuration_main_window} , settings_ {settings} , configuration_dialog_ {instance_key, settings, this} , updating_models_ {false} , band_edited_ {false} , desired_frequency_ {0u} , RX_frequency_ {"RX"} , TX_frequency_ {"TX"} { ui_->setupUi (this); setWindowTitle (QApplication::applicationName () + " - " + title); // mode "Unknown" is display only ui_->mode_combo_box->setItemData (ui_->mode_combo_box->findText ("Unknown"), combo_box_item_disabled, Qt::UserRole - 1); // setup status bar widgets statusBar ()->insertPermanentWidget (0, &TX_frequency_); statusBar ()->insertPermanentWidget (0, &RX_frequency_); // assign push button ids ui_->TX_button_group->setId (ui_->vfo_0_TX_push_button, 0); ui_->TX_button_group->setId (ui_->vfo_1_TX_push_button, 1); // enable live band combo box entry validation and action auto band_validator = new LiveFrequencyValidator {ui_->band_combo_box , configuration_dialog_.bands () , configuration_dialog_.frequencies () , this}; ui_->band_combo_box->setValidator (band_validator); connect (band_validator, &LiveFrequencyValidator::valid, this, &TestConfiguration::impl::band_changed); connect (ui_->band_combo_box->lineEdit (), &QLineEdit::textEdited, [this] (QString const&) {band_edited_ = true;}); // hook up band data model ui_->band_combo_box->setModel (configuration_dialog_.frequencies ()); // combo box drop downs are limited to the drop down selector width, // this almost random increase improves the situation ui_->band_combo_box->view ()->setMinimumWidth (ui_->band_combo_box->view ()->sizeHintForColumn (0) + 10); // hook up configuration signals connect (&configuration_dialog_, &Configuration::transceiver_update, this, &TestConfiguration::impl::handle_transceiver_update); connect (&configuration_dialog_, &Configuration::transceiver_failure, this, &TestConfiguration::impl::handle_transceiver_failure); // hook up configuration slots connect (this, &TestConfiguration::impl::new_frequency, &configuration_dialog_, &Configuration::transceiver_frequency); connect (this, &TestConfiguration::impl::new_tx_frequency, &configuration_dialog_, &Configuration::transceiver_tx_frequency); load_models (); read_settings (); show (); } void TestConfiguration::impl::closeEvent (QCloseEvent * e) { write_settings (); QMainWindow::closeEvent (e); } void TestConfiguration::impl::on_configuration_action_triggered () { qDebug () << "TestConfiguration::on_configuration_action_triggered"; if (QDialog::Accepted == configuration_dialog_.exec ()) { qDebug () << "TestConfiguration::on_configuration_action_triggered: Configuration changed"; qDebug () << "TestConfiguration::on_configuration_action_triggered: rig is" << configuration_dialog_.rig_name (); if (configuration_dialog_.restart_audio_input ()) { qDebug () << "Audio Device Changes - Configuration changes require an audio input device to be restarted"; } if (configuration_dialog_.restart_audio_output ()) { qDebug () << "Audio Device Changes - Configuration changes require an audio output device to be restarted"; } load_models (); } else { qDebug () << "TestConfiguration::on_configuration_action_triggered: Confiugration changes cancelled"; } } void TestConfiguration::impl::on_band_combo_box_activated (int index) { qDebug () << "TestConfiguration::on_band_combo_box_activated: " << ui_->band_combo_box->currentText (); auto model = configuration_dialog_.frequencies (); auto value = model->data (model->index (index, 2), Qt::DisplayRole).toString (); if (configuration_dialog_.bands ()->data (QModelIndex {}).toString () == value) { ui_->band_combo_box->lineEdit ()->setStyleSheet ("QLineEdit {color: yellow; background-color : red;}"); } else { ui_->band_combo_box->lineEdit ()->setStyleSheet ({}); } ui_->band_combo_box->setCurrentText (value); auto f = model->data (model->index (index, 0), Qt::UserRole + 1).value (); band_edited_ = true; band_changed (f); } void TestConfiguration::impl::band_changed (Frequency f) { if (band_edited_) { band_edited_ = false; frequency_changed (f); sync_rig (); } } void TestConfiguration::impl::frequency_changed (Frequency f) { desired_frequency_ = f; // lookup band auto bands_model = configuration_dialog_.bands (); ui_->band_combo_box->setCurrentText (bands_model->data (bands_model->find (f)).toString ()); } void TestConfiguration::impl::on_sync_push_button_clicked (bool /* checked */) { qDebug () << "TestConfiguration::on_sync_push_button_clicked"; auto model = configuration_dialog_.frequencies (); auto model_index = model->index (ui_->band_combo_box->currentIndex (), 0); desired_frequency_ = model->data (model_index, Qt::UserRole + 1).value (); sync_rig (); } void TestConfiguration::impl::on_mode_combo_box_activated (int index) { qDebug () << "TestConfiguration::on_vfo_A_mode_combo_box_activated: " << static_cast (index); // reset combo box back to current mode and let status update do the actual change ui_->mode_combo_box->setCurrentIndex (rig_state_.mode ()); Q_EMIT configuration_dialog_.transceiver_mode (static_cast (index)); } void TestConfiguration::impl::on_TX_offset_spin_box_valueChanged (int value) { qDebug () << "TestConfiguration::on_TX_offset_spin_box_editingFinished: " << value; Q_EMIT new_tx_frequency (rig_state_.frequency () + value); } void TestConfiguration::impl::on_PTT_push_button_clicked (bool checked) { qDebug () << "TestConfiguration::on_PTT_push_button_clicked: " << (checked ? "true" : "false"); // reset button and let status update do the actual checking ui_->PTT_push_button->setChecked (rig_state_.ptt ()); Q_EMIT configuration_dialog_.transceiver_ptt (checked); } void TestConfiguration::impl::on_split_push_button_clicked (bool checked) { qDebug () << "TestConfiguration::on_split_push_button_clicked: " << (checked ? "true" : "false"); // reset button and let status update do the actual checking ui_->split_push_button->setChecked (rig_state_.split ()); if (checked) { Q_EMIT new_tx_frequency (rig_state_.frequency () + ui_->TX_offset_spin_box->value ()); } else { Q_EMIT new_tx_frequency (); } } void TestConfiguration::impl::sync_rig () { if (!updating_models_) { if (configuration_dialog_.transceiver_online (true)) { if (configuration_dialog_.split_mode ()) { Q_EMIT new_frequency (desired_frequency_); Q_EMIT new_tx_frequency (desired_frequency_ + ui_->TX_offset_spin_box->value ()); } else { Q_EMIT new_frequency (desired_frequency_); Q_EMIT new_tx_frequency (); } } } } void TestConfiguration::impl::handle_transceiver_update (Transceiver::TransceiverState s) { rig_state_ = s; auto model = configuration_dialog_.frequencies (); bool valid {false}; for (int row = 0; row < model->rowCount (); ++row) { auto working_frequency = model->data (model->index (row, 0), Qt::UserRole + 1).value (); if (std::abs (static_cast (working_frequency - s.frequency ())) < 10000) { valid = true; } } if (!valid) { ui_->vfo_0_lcd_number->setStyleSheet ("QLCDNumber {background-color: red;}"); } else { ui_->vfo_0_lcd_number->setStyleSheet (QString {}); } ui_->vfo_0_lcd_number->display (Radio::pretty_frequency_MHz_string (s.frequency ())); if (s.split ()) { ui_->vfo_1_lcd_number->display (Radio::pretty_frequency_MHz_string (s.tx_frequency ())); valid = false; for (int row = 0; row < model->rowCount (); ++row) { auto working_frequency = model->data (model->index (row, 0), Qt::UserRole + 1).value (); if (std::abs (static_cast (working_frequency - s.tx_frequency ())) < 10000) { valid = true; } } if (!valid) { ui_->vfo_1_lcd_number->setStyleSheet ("QLCDNumber {background-color: red;}"); } else { ui_->vfo_1_lcd_number->setStyleSheet (QString {}); } ui_->vfo_1_lcd_number->show (); ui_->vfo_1_TX_push_button->show (); } else { ui_->vfo_1_lcd_number->hide (); ui_->vfo_1_TX_push_button->hide (); } frequency_changed (s.frequency ()); ui_->radio_widget->setEnabled (s.online ()); ui_->mode_combo_box->setCurrentIndex (s.mode ()); RX_frequency_.setText (Radio::pretty_frequency_MHz_string (s.frequency ())); TX_frequency_.setText (Radio::pretty_frequency_MHz_string (s.split () ? s.tx_frequency () : s.frequency ())); ui_->TX_button_group->button (s.split ())->setChecked (true); ui_->PTT_push_button->setChecked (s.ptt ()); ui_->split_push_button->setChecked (s.split ()); ui_->radio_widget->setEnabled (s.online ()); } void TestConfiguration::impl::handle_transceiver_failure (QString reason) { ui_->radio_widget->setEnabled (false); ui_->vfo_0_lcd_number->display (LCD_error); ui_->vfo_1_lcd_number->display (LCD_error); information_message_box ("Rig failure", reason); } void TestConfiguration::impl::read_settings () { settings_->beginGroup ("TestConfiguration"); resize (settings_->value ("window/size", size ()).toSize ()); move (settings_->value ("window/pos", pos ()).toPoint ()); restoreState (settings_->value ("window/state", saveState ()).toByteArray ()); ui_->band_combo_box->setCurrentText (settings_->value ("Band").toString ()); settings_->endGroup (); settings_->beginGroup ("Configuration"); callsign_ = settings_->value ("MyCall").toString (); settings_->endGroup (); } void TestConfiguration::impl::write_settings () { settings_->beginGroup ("TestConfiguration"); settings_->setValue ("window/size", size ()); settings_->setValue ("window/pos", pos ()); settings_->setValue ("window/state", saveState ()); settings_->setValue ("Band", ui_->band_combo_box->currentText ()); settings_->endGroup (); } void TestConfiguration::impl::load_models () { updating_models_ = true; ui_->frequency_group_box->setTitle (configuration_dialog_.rig_name ()); // if (auto rig = configuration_dialog_.rig (false)) // don't open radio if (configuration_dialog_.transceiver_online (false)) // don't open radio { Q_EMIT configuration_dialog_.sync_transceiver (true); } else { ui_->radio_widget->setEnabled (false); ui_->vfo_0_lcd_number->display (Radio::pretty_frequency_MHz_string (static_cast (0))); ui_->vfo_1_lcd_number->display (Radio::pretty_frequency_MHz_string (static_cast (0))); } if (!configuration_dialog_.split_mode ()) { ui_->vfo_1_lcd_number->hide (); ui_->vfo_1_TX_push_button->hide (); } updating_models_ = false; } void TestConfiguration::impl::information_message_box (QString const& reason, QString const& detail) { qDebug () << "TestConfiguration::information_message_box: reason =" << reason << "detail =" << detail; QMessageBox mb; mb.setWindowFlags (mb.windowFlags () | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint); mb.setText (reason); if (!detail.isEmpty ()) { mb.setDetailedText (detail); } mb.setStandardButtons (QMessageBox::Ok); mb.setDefaultButton (QMessageBox::Ok); mb.setIcon (QMessageBox::Information); mb.exec (); }