mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-31 04:50:34 -04:00 
			
		
		
		
	all types of build. CMake builds use 'svn info' (the git-svn equivalent is also supported) to get the real latest revision of the workspace that is used to source a build. If the sources are not in VCS workspace (build from source snapshot archive for example) then the $Rev$ svn keyword expansion in mainwindow.cpp is used despite its issues with accuracy. Non-CMake builds use the $Rev$ keyword expansion where possible. If a CMake build is from a VCS workspace with local modifications; a '-dirty' suffix is added to the revision number to denote that. If no revision number information can be found the word 'local' is used as a revision number. The revision specification is used in the WSJT-X "about" box and is sent to PSKReporter.info as part of the local station information (this can be viewed at the statistics page http://pskreporter.info/cgi-bin/pskstats.pl). git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@4017 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
		
			
				
	
	
		
			472 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			472 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "TestConfiguration.hpp"
 | |
| 
 | |
| #include <cstdlib>
 | |
| 
 | |
| #include <QApplication>
 | |
| #include <QSettings>
 | |
| #include <QMainWindow>
 | |
| #include <QLabel>
 | |
| #include <QDir>
 | |
| #include <QMessageBox>
 | |
| #include <QLineEdit>
 | |
| #include <QDebug>
 | |
| #include <QSortFilterProxyModel>
 | |
| 
 | |
| #include "revision_utils.hpp"
 | |
| #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 (program_title (revision ()));
 | |
| 
 | |
|   // 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<Frequency> ();
 | |
| 
 | |
|   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<Frequency> ();
 | |
| 
 | |
|   sync_rig ();
 | |
| }
 | |
| 
 | |
| void TestConfiguration::impl::on_mode_combo_box_activated (int index)
 | |
| {
 | |
|   qDebug () << "TestConfiguration::on_vfo_A_mode_combo_box_activated: " << static_cast<Transceiver::MODE> (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<Transceiver::MODE> (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<Frequency> ();
 | |
|       if (std::abs (static_cast<Radio::FrequencyDelta> (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<Frequency> ();
 | |
|           if (std::abs (static_cast<Radio::FrequencyDelta> (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<Frequency> (0)));
 | |
|       ui_->vfo_1_lcd_number->display (Radio::pretty_frequency_MHz_string (static_cast<Frequency> (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 ();
 | |
| }
 |