WSJT-X/TestConfiguration.cpp
Bill Somerville 4537ac471d Reducing the number of files dependent on svnversion.h without
compromising qmake builds. Now it is required to directly include
svnversion.h to get the SVNVERSION macro defined.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@3955 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
2014-03-29 02:51:07 +00:00

473 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 "svnversion.h"
#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<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 ();
}