2567 lines
		
	
	
		
			98 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			2567 lines
		
	
	
		
			98 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								#include "Configuration.hpp"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Read me!
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// This file defines a configuration dialog with the user. The general
							 | 
						||
| 
								 | 
							
								// strategy is to expose agreed  configuration parameters via a custom
							 | 
						||
| 
								 | 
							
								// interface (See  Configuration.hpp). The state exposed  through this
							 | 
						||
| 
								 | 
							
								// public   interface  reflects   stored  or   derived  data   in  the
							 | 
						||
| 
								 | 
							
								// Configuration::impl object.   The Configuration::impl  structure is
							 | 
						||
| 
								 | 
							
								// an implementation of the PIMPL (a.k.a.  Cheshire Cat or compilation
							 | 
						||
| 
								 | 
							
								// firewall) implementation hiding idiom that allows internal state to
							 | 
						||
| 
								 | 
							
								// be completely removed from the public interface.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// There  is a  secondary level  of parameter  storage which  reflects
							 | 
						||
| 
								 | 
							
								// current settings UI  state, these parameters are not  copied to the
							 | 
						||
| 
								 | 
							
								// state   store  that   the  public   interface  exposes   until  the
							 | 
						||
| 
								 | 
							
								// Configuration:impl::accept() operation is  successful. The accept()
							 | 
						||
| 
								 | 
							
								// operation is  tied to the settings  OK button. The normal  and most
							 | 
						||
| 
								 | 
							
								// convenient place to store this intermediate settings UI state is in
							 | 
						||
| 
								 | 
							
								// the data models of the UI  controls, if that is not convenient then
							 | 
						||
| 
								 | 
							
								// separate member variables  must be used to store that  state. It is
							 | 
						||
| 
								 | 
							
								// important for the user experience that no publicly visible settings
							 | 
						||
| 
								 | 
							
								// are changed  while the  settings UI are  changed i.e.  all settings
							 | 
						||
| 
								 | 
							
								// changes   must    be   deferred   until   the    "OK"   button   is
							 | 
						||
| 
								 | 
							
								// clicked. Conversely, all changes must  be discarded if the settings
							 | 
						||
| 
								 | 
							
								// UI "Cancel" button is clicked.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// There is  a complication related  to the radio interface  since the
							 | 
						||
| 
								 | 
							
								// this module offers  the facility to test the  radio interface. This
							 | 
						||
| 
								 | 
							
								// test means  that the  public visibility to  the radio  being tested
							 | 
						||
| 
								 | 
							
								// must be  changed.  To  maintain the  illusion of  deferring changes
							 | 
						||
| 
								 | 
							
								// until they  are accepted, the  original radio related  settings are
							 | 
						||
| 
								 | 
							
								// stored upon showing  the UI and restored if the  UI is dismissed by
							 | 
						||
| 
								 | 
							
								// canceling.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// It  should be  noted that  the  settings UI  lives as  long as  the
							 | 
						||
| 
								 | 
							
								// application client that uses it does. It is simply shown and hidden
							 | 
						||
| 
								 | 
							
								// as it  is needed rather than  creating it on demand.  This strategy
							 | 
						||
| 
								 | 
							
								// saves a  lot of  expensive UI  drawing at the  expense of  a little
							 | 
						||
| 
								 | 
							
								// storage and  gives a  convenient place  to deliver  settings values
							 | 
						||
| 
								 | 
							
								// from.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Here is an overview of the high level flow of this module:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 1)  On  construction the  initial  environment  is initialized  and
							 | 
						||
| 
								 | 
							
								// initial   values  for   settings  are   read  from   the  QSettings
							 | 
						||
| 
								 | 
							
								// database. At  this point  default values for  any new  settings are
							 | 
						||
| 
								 | 
							
								// established by  providing a  default value  to the  QSettings value
							 | 
						||
| 
								 | 
							
								// queries. This should be the only place where a hard coded value for
							 | 
						||
| 
								 | 
							
								// a   settings  item   is   defined.   Any   remaining  one-time   UI
							 | 
						||
| 
								 | 
							
								// initialization is also done. At the end of the constructor a method
							 | 
						||
| 
								 | 
							
								// initialize_models()  is called  to  load the  UI  with the  current
							 | 
						||
| 
								 | 
							
								// settings values.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 2) When the settings UI is displayed by a client calling the exec()
							 | 
						||
| 
								 | 
							
								// operation, only temporary state need be stored as the UI state will
							 | 
						||
| 
								 | 
							
								// already mirror the publicly visible settings state.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 3) As  the user makes  changes to  the settings UI  only validation
							 | 
						||
| 
								 | 
							
								// need be  carried out since the  UI control data models  are used as
							 | 
						||
| 
								 | 
							
								// the temporary store of unconfirmed settings.  As some settings will
							 | 
						||
| 
								 | 
							
								// depend  on each  other a  validate() operation  is available,  this
							 | 
						||
| 
								 | 
							
								// operation implements a check of any complex multi-field values.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 4) If the  user discards the settings changes by  dismissing the UI
							 | 
						||
| 
								 | 
							
								// with the  "Cancel" button;  the reject()  operation is  called. The
							 | 
						||
| 
								 | 
							
								// reject() operation calls initialize_models()  which will revert all
							 | 
						||
| 
								 | 
							
								// the  UI visible  state  to  the values  as  at  the initial  exec()
							 | 
						||
| 
								 | 
							
								// operation.  No   changes  are  moved   into  the  data   fields  in
							 | 
						||
| 
								 | 
							
								// Configuration::impl that  reflect the  settings state  published by
							 | 
						||
| 
								 | 
							
								// the public interface (Configuration.hpp).
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 5) If  the user accepts the  settings changes by dismissing  the UI
							 | 
						||
| 
								 | 
							
								// with the "OK" button; the  accept() operation is called which calls
							 | 
						||
| 
								 | 
							
								// the validate() operation  again and, if it passes,  the fields that
							 | 
						||
| 
								 | 
							
								// are used  to deliver  the settings  state are  updated from  the UI
							 | 
						||
| 
								 | 
							
								// control models  or other temporary  state variables. At the  end of
							 | 
						||
| 
								 | 
							
								// the accept()  operation, just  before hiding  the UI  and returning
							 | 
						||
| 
								 | 
							
								// control to the caller; the new  settings values are stored into the
							 | 
						||
| 
								 | 
							
								// settings database by a call to the write_settings() operation, thus
							 | 
						||
| 
								 | 
							
								// ensuring that  settings changes are  saved even if  the application
							 | 
						||
| 
								 | 
							
								// crashes or is subsequently killed.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 6)  On  destruction,  which   only  happens  when  the  application
							 | 
						||
| 
								 | 
							
								// terminates,  the settings  are saved  to the  settings database  by
							 | 
						||
| 
								 | 
							
								// calling the  write_settings() operation. This is  largely redundant
							 | 
						||
| 
								 | 
							
								// but is still done to save the default values of any new settings on
							 | 
						||
| 
								 | 
							
								// an initial run.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// To add a new setting:
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 1) Update the UI with the new widget to view and change the value.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 2)  Add  a member  to  Configuration::impl  to store  the  accepted
							 | 
						||
| 
								 | 
							
								// setting state. If the setting state is dynamic; add a new signal to
							 | 
						||
| 
								 | 
							
								// broadcast the setting value.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 3) Add a  query method to the  public interface (Configuration.hpp)
							 | 
						||
| 
								 | 
							
								// to access the  new setting value. If the settings  is dynamic; this
							 | 
						||
| 
								 | 
							
								// step  is optional  since  value  changes will  be  broadcast via  a
							 | 
						||
| 
								 | 
							
								// signal.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 4) Add a forwarding operation to implement the new query (3) above.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 5)  Add a  settings read  call to  read_settings() with  a sensible
							 | 
						||
| 
								 | 
							
								// default value. If  the setting value is dynamic, add  a signal emit
							 | 
						||
| 
								 | 
							
								// call to broadcast the setting value change.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 6) Add  code to  initialize_models() to  load the  widget control's
							 | 
						||
| 
								 | 
							
								// data model with the current value.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 7) If there is no convenient data model field, add a data member to
							 | 
						||
| 
								 | 
							
								// store the proposed new value. Ensure  this member has a valid value
							 | 
						||
| 
								 | 
							
								// on exit from read_settings().
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 8)  Add  any  required  inter-field validation  to  the  validate()
							 | 
						||
| 
								 | 
							
								// operation.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 9) Add code to the accept()  operation to extract the setting value
							 | 
						||
| 
								 | 
							
								// from  the  widget   control  data  model  and  load   it  into  the
							 | 
						||
| 
								 | 
							
								// Configuration::impl  member  that  reflects  the  publicly  visible
							 | 
						||
| 
								 | 
							
								// setting state. If  the setting value is dynamic; add  a signal emit
							 | 
						||
| 
								 | 
							
								// call to broadcast any changed state of the setting.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// 10) Add  a settings  write call  to save the  setting value  to the
							 | 
						||
| 
								 | 
							
								// settings database.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <stdexcept>
							 | 
						||
| 
								 | 
							
								#include <iterator>
							 | 
						||
| 
								 | 
							
								#include <algorithm>
							 | 
						||
| 
								 | 
							
								#include <functional>
							 | 
						||
| 
								 | 
							
								#include <limits>
							 | 
						||
| 
								 | 
							
								#include <cmath>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <QApplication>
							 | 
						||
| 
								 | 
							
								#include <QMetaType>
							 | 
						||
| 
								 | 
							
								#include <QList>
							 | 
						||
| 
								 | 
							
								#include <QSettings>
							 | 
						||
| 
								 | 
							
								#include <QAudioDeviceInfo>
							 | 
						||
| 
								 | 
							
								#include <QAudioInput>
							 | 
						||
| 
								 | 
							
								#include <QDialog>
							 | 
						||
| 
								 | 
							
								#include <QAction>
							 | 
						||
| 
								 | 
							
								#include <QFileDialog>
							 | 
						||
| 
								 | 
							
								#include <QDir>
							 | 
						||
| 
								 | 
							
								#include <QTemporaryFile>
							 | 
						||
| 
								 | 
							
								#include <QFormLayout>
							 | 
						||
| 
								 | 
							
								#include <QString>
							 | 
						||
| 
								 | 
							
								#include <QStringList>
							 | 
						||
| 
								 | 
							
								#include <QStringListModel>
							 | 
						||
| 
								 | 
							
								#include <QLineEdit>
							 | 
						||
| 
								 | 
							
								#include <QRegExpValidator>
							 | 
						||
| 
								 | 
							
								#include <QIntValidator>
							 | 
						||
| 
								 | 
							
								#include <QThread>
							 | 
						||
| 
								 | 
							
								#include <QTimer>
							 | 
						||
| 
								 | 
							
								#include <QStandardPaths>
							 | 
						||
| 
								 | 
							
								#include <QFont>
							 | 
						||
| 
								 | 
							
								#include <QFontDialog>
							 | 
						||
| 
								 | 
							
								#include <QColorDialog>
							 | 
						||
| 
								 | 
							
								#include <QSerialPortInfo>
							 | 
						||
| 
								 | 
							
								#include <QScopedPointer>
							 | 
						||
| 
								 | 
							
								#include <QDebug>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "pimpl_impl.hpp"
							 | 
						||
| 
								 | 
							
								#include "qt_helpers.hpp"
							 | 
						||
| 
								 | 
							
								#include "MetaDataRegistry.hpp"
							 | 
						||
| 
								 | 
							
								#include "SettingsGroup.hpp"
							 | 
						||
| 
								 | 
							
								#include "FrequencyLineEdit.hpp"
							 | 
						||
| 
								 | 
							
								#include "CandidateKeyFilter.hpp"
							 | 
						||
| 
								 | 
							
								#include "ForeignKeyDelegate.hpp"
							 | 
						||
| 
								 | 
							
								#include "TransceiverFactory.hpp"
							 | 
						||
| 
								 | 
							
								#include "Transceiver.hpp"
							 | 
						||
| 
								 | 
							
								#include "Bands.hpp"
							 | 
						||
| 
								 | 
							
								#include "Modes.hpp"
							 | 
						||
| 
								 | 
							
								#include "FrequencyList.hpp"
							 | 
						||
| 
								 | 
							
								#include "StationList.hpp"
							 | 
						||
| 
								 | 
							
								#include "NetworkServerLookup.hpp"
							 | 
						||
| 
								 | 
							
								#include "MessageBox.hpp"
							 | 
						||
| 
								 | 
							
								#include "MaidenheadLocatorValidator.hpp"
							 | 
						||
| 
								 | 
							
								#include "CallsignValidator.hpp"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "ui_Configuration.h"
							 | 
						||
| 
								 | 
							
								#include "moc_Configuration.cpp"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // 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);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//  QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"};
							 | 
						||
| 
								 | 
							
								  QRegExp message_alphabet {"[- @A-Za-z0-9+./?#<>]*"};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Dialog to get a new Frequency item
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								class FrequencyDialog final
							 | 
						||
| 
								 | 
							
								  : public QDialog
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  using Item = FrequencyList::Item;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  explicit FrequencyDialog (Modes * modes_model, QWidget * parent = nullptr)
							 | 
						||
| 
								 | 
							
								    : QDialog {parent}
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    setWindowTitle (QApplication::applicationName () + " - " +
							 | 
						||
| 
								 | 
							
								                    tr ("Add Frequency"));
							 | 
						||
| 
								 | 
							
								    mode_combo_box_.setModel (modes_model);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    auto form_layout = new QFormLayout ();
							 | 
						||
| 
								 | 
							
								    form_layout->addRow (tr ("&Mode:"), &mode_combo_box_);
							 | 
						||
| 
								 | 
							
								    form_layout->addRow (tr ("&Frequency (MHz):"), &frequency_line_edit_);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    auto main_layout = new QVBoxLayout (this);
							 | 
						||
| 
								 | 
							
								    main_layout->addLayout (form_layout);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    auto button_box = new QDialogButtonBox {QDialogButtonBox::Ok | QDialogButtonBox::Cancel};
							 | 
						||
| 
								 | 
							
								    main_layout->addWidget (button_box);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    connect (button_box, &QDialogButtonBox::accepted, this, &FrequencyDialog::accept);
							 | 
						||
| 
								 | 
							
								    connect (button_box, &QDialogButtonBox::rejected, this, &FrequencyDialog::reject);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Item item () const
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    return {frequency_line_edit_.frequency (), Modes::value (mode_combo_box_.currentText ())};
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  QComboBox mode_combo_box_;
							 | 
						||
| 
								 | 
							
								  FrequencyLineEdit frequency_line_edit_;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Dialog to get a new Station item
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								class StationDialog final
							 | 
						||
| 
								 | 
							
								  : public QDialog
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  explicit StationDialog (StationList const * stations, Bands * bands, QWidget * parent = nullptr)
							 | 
						||
| 
								 | 
							
								    : QDialog {parent}
							 | 
						||
| 
								 | 
							
								    , filtered_bands_ {new CandidateKeyFilter {bands, stations, 0, 0}}
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    setWindowTitle (QApplication::applicationName () + " - " + tr ("Add Station"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    band_.setModel (filtered_bands_.data ());
							 | 
						||
| 
								 | 
							
								      
							 | 
						||
| 
								 | 
							
								    auto form_layout = new QFormLayout ();
							 | 
						||
| 
								 | 
							
								    form_layout->addRow (tr ("&Band:"), &band_);
							 | 
						||
| 
								 | 
							
								    form_layout->addRow (tr ("&Offset (MHz):"), &delta_);
							 | 
						||
| 
								 | 
							
								    form_layout->addRow (tr ("&Antenna:"), &description_);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    auto main_layout = new QVBoxLayout (this);
							 | 
						||
| 
								 | 
							
								    main_layout->addLayout (form_layout);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    auto button_box = new QDialogButtonBox {QDialogButtonBox::Ok | QDialogButtonBox::Cancel};
							 | 
						||
| 
								 | 
							
								    main_layout->addWidget (button_box);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    connect (button_box, &QDialogButtonBox::accepted, this, &StationDialog::accept);
							 | 
						||
| 
								 | 
							
								    connect (button_box, &QDialogButtonBox::rejected, this, &StationDialog::reject);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (delta_.text ().isEmpty ())
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        delta_.setText ("0");
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  StationList::Station station () const
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    return {band_.currentText (), delta_.frequency_delta (), description_.text ()};
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  int exec () override
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    filtered_bands_->set_active_key ();
							 | 
						||
| 
								 | 
							
								    return QDialog::exec ();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  QScopedPointer<CandidateKeyFilter> filtered_bands_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QComboBox band_;
							 | 
						||
| 
								 | 
							
								  FrequencyDeltaLineEdit delta_;
							 | 
						||
| 
								 | 
							
								  QLineEdit description_;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								class RearrangableMacrosModel
							 | 
						||
| 
								 | 
							
								  : public QStringListModel
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  Qt::ItemFlags flags (QModelIndex const& index) const override
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    auto flags = QStringListModel::flags (index);
							 | 
						||
| 
								 | 
							
								    if (index.isValid ())
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        // disallow drop onto existing items
							 | 
						||
| 
								 | 
							
								        flags &= ~Qt::ItemIsDropEnabled;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    return flags;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Class MessageItemDelegate
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								//	Item delegate for message entry such as free text message macros.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								class MessageItemDelegate final
							 | 
						||
| 
								 | 
							
								  : public QStyledItemDelegate
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  explicit MessageItemDelegate (QObject * parent = nullptr)
							 | 
						||
| 
								 | 
							
								    : QStyledItemDelegate {parent}
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QWidget * createEditor (QWidget * parent
							 | 
						||
| 
								 | 
							
								                          , QStyleOptionViewItem const& /* option*/
							 | 
						||
| 
								 | 
							
								                          , QModelIndex const& /* index */
							 | 
						||
| 
								 | 
							
								                          ) const override
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    auto editor = new QLineEdit {parent};
							 | 
						||
| 
								 | 
							
								    editor->setFrame (false);
							 | 
						||
| 
								 | 
							
								    editor->setValidator (new QRegExpValidator {message_alphabet, editor});
							 | 
						||
| 
								 | 
							
								    return editor;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Internal implementation of the Configuration class.
							 | 
						||
| 
								 | 
							
								class Configuration::impl final
							 | 
						||
| 
								 | 
							
								  : public QDialog
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  Q_OBJECT;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								  using FrequencyDelta = Radio::FrequencyDelta;
							 | 
						||
| 
								 | 
							
								  using port_type = Configuration::port_type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  explicit impl (Configuration * self, QDir const& temp_directory,
							 | 
						||
| 
								 | 
							
								                 QSettings * settings, QWidget * parent);
							 | 
						||
| 
								 | 
							
								  ~impl ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  bool have_rig ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void transceiver_frequency (Frequency);
							 | 
						||
| 
								 | 
							
								  void transceiver_tx_frequency (Frequency);
							 | 
						||
| 
								 | 
							
								  void transceiver_mode (MODE);
							 | 
						||
| 
								 | 
							
								  void transceiver_ptt (bool);
							 | 
						||
| 
								 | 
							
								  void sync_transceiver (bool force_signal);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Q_SLOT int exec () override;
							 | 
						||
| 
								 | 
							
								  Q_SLOT void accept () override;
							 | 
						||
| 
								 | 
							
								  Q_SLOT void reject () override;
							 | 
						||
| 
								 | 
							
								  Q_SLOT void done (int) override;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								  typedef QList<QAudioDeviceInfo> AudioDevices;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void read_settings ();
							 | 
						||
| 
								 | 
							
								  void write_settings ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  bool load_audio_devices (QAudio::Mode, QComboBox *, QAudioDeviceInfo *);
							 | 
						||
| 
								 | 
							
								  void update_audio_channels (QComboBox const *, int, QComboBox *, bool);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void set_application_font (QFont const&);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  void initialize_models ();
							 | 
						||
| 
								 | 
							
								  bool split_mode () const
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    return
							 | 
						||
| 
								 | 
							
								      (WSJT_RIG_NONE_CAN_SPLIT || !rig_is_dummy_) &&
							 | 
						||
| 
								 | 
							
								      (rig_params_.split_mode != TransceiverFactory::split_mode_none);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  void set_cached_mode ();
							 | 
						||
| 
								 | 
							
								  bool open_rig (bool force = false);
							 | 
						||
| 
								 | 
							
								  //bool set_mode ();
							 | 
						||
| 
								 | 
							
								  void close_rig ();
							 | 
						||
| 
								 | 
							
								  TransceiverFactory::ParameterPack gather_rig_data ();
							 | 
						||
| 
								 | 
							
								  void enumerate_rigs ();
							 | 
						||
| 
								 | 
							
								  void set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								  bool validate ();
							 | 
						||
| 
								 | 
							
								  void fill_port_combo_box (QComboBox *);
							 | 
						||
| 
								 | 
							
								  Frequency apply_calibration (Frequency) const;
							 | 
						||
| 
								 | 
							
								  Frequency remove_calibration (Frequency) const;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_font_push_button_clicked ();
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_decoded_text_font_push_button_clicked ();
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_PTT_port_combo_box_activated (int);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_CAT_port_combo_box_activated (int);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_CAT_serial_baud_combo_box_currentIndexChanged (int);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_CAT_data_bits_button_group_buttonClicked (int);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_CAT_stop_bits_button_group_buttonClicked (int);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_CAT_handshake_button_group_buttonClicked (int);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_CAT_poll_interval_spin_box_valueChanged (int);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_split_mode_button_group_buttonClicked (int);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_test_CAT_push_button_clicked ();
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_test_PTT_push_button_clicked (bool checked);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_force_DTR_combo_box_currentIndexChanged (int);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_force_RTS_combo_box_currentIndexChanged (int);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_rig_combo_box_currentIndexChanged (int);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_sound_input_combo_box_currentTextChanged (QString const&);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_sound_output_combo_box_currentTextChanged (QString const&);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_add_macro_push_button_clicked (bool = false);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_delete_macro_push_button_clicked (bool = false);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_PTT_method_button_group_buttonClicked (int);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_add_macro_line_edit_editingFinished ();
							 | 
						||
| 
								 | 
							
								  Q_SLOT void delete_macro ();
							 | 
						||
| 
								 | 
							
								  void delete_selected_macros (QModelIndexList);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_save_path_select_push_button_clicked (bool);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_azel_path_select_push_button_clicked (bool);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_calibration_intercept_spin_box_valueChanged (double);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_calibration_slope_ppm_spin_box_valueChanged (double);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void delete_frequencies ();
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_reset_frequencies_push_button_clicked (bool);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void insert_frequency ();
							 | 
						||
| 
								 | 
							
								  Q_SLOT void delete_stations ();
							 | 
						||
| 
								 | 
							
								  Q_SLOT void insert_station ();
							 | 
						||
| 
								 | 
							
								  Q_SLOT void handle_transceiver_update (TransceiverState const&, unsigned sequence_number);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void handle_transceiver_failure (QString const& reason);
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_pbCQmsg_clicked();
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_pbMyCall_clicked();
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_pbTxMsg_clicked();
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_pbNewDXCC_clicked();
							 | 
						||
| 
								 | 
							
								  Q_SLOT void on_pbNewCall_clicked();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // typenames used as arguments must match registered type names :(
							 | 
						||
| 
								 | 
							
								  Q_SIGNAL void start_transceiver (unsigned seqeunce_number) const;
							 | 
						||
| 
								 | 
							
								  Q_SIGNAL void set_transceiver (Transceiver::TransceiverState const&,
							 | 
						||
| 
								 | 
							
								                                 unsigned sequence_number) const;
							 | 
						||
| 
								 | 
							
								  Q_SIGNAL void stop_transceiver () const;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Configuration * const self_;	// back pointer to public interface
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QThread * transceiver_thread_;
							 | 
						||
| 
								 | 
							
								  TransceiverFactory transceiver_factory_;
							 | 
						||
| 
								 | 
							
								  QList<QMetaObject::Connection> rig_connections_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QScopedPointer<Ui::configuration_dialog> ui_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QSettings * settings_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QDir doc_dir_;
							 | 
						||
| 
								 | 
							
								  QDir data_dir_;
							 | 
						||
| 
								 | 
							
								  QDir temp_dir_;
							 | 
						||
| 
								 | 
							
								  QDir default_save_directory_;
							 | 
						||
| 
								 | 
							
								  QDir save_directory_;
							 | 
						||
| 
								 | 
							
								  QDir default_azel_directory_;
							 | 
						||
| 
								 | 
							
								  QDir azel_directory_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QFont font_;
							 | 
						||
| 
								 | 
							
								  QFont next_font_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QFont decoded_text_font_;
							 | 
						||
| 
								 | 
							
								  QFont next_decoded_text_font_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  bool restart_sound_input_device_;
							 | 
						||
| 
								 | 
							
								  bool restart_sound_output_device_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Type2MsgGen type_2_msg_gen_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QStringListModel macros_;
							 | 
						||
| 
								 | 
							
								  RearrangableMacrosModel next_macros_;
							 | 
						||
| 
								 | 
							
								  QAction * macro_delete_action_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Bands bands_;
							 | 
						||
| 
								 | 
							
								  Modes modes_;
							 | 
						||
| 
								 | 
							
								  FrequencyList frequencies_;
							 | 
						||
| 
								 | 
							
								  FrequencyList next_frequencies_;
							 | 
						||
| 
								 | 
							
								  StationList stations_;
							 | 
						||
| 
								 | 
							
								  StationList next_stations_;
							 | 
						||
| 
								 | 
							
								  FrequencyDelta current_offset_;
							 | 
						||
| 
								 | 
							
								  FrequencyDelta current_tx_offset_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QAction * frequency_delete_action_;
							 | 
						||
| 
								 | 
							
								  QAction * frequency_insert_action_;
							 | 
						||
| 
								 | 
							
								  FrequencyDialog * frequency_dialog_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QAction * station_delete_action_;
							 | 
						||
| 
								 | 
							
								  QAction * station_insert_action_;
							 | 
						||
| 
								 | 
							
								  StationDialog * station_dialog_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  TransceiverFactory::ParameterPack rig_params_;
							 | 
						||
| 
								 | 
							
								  TransceiverFactory::ParameterPack saved_rig_params_;
							 | 
						||
| 
								 | 
							
								  TransceiverFactory::Capabilities::PortType last_port_type_;
							 | 
						||
| 
								 | 
							
								  bool rig_is_dummy_;
							 | 
						||
| 
								 | 
							
								  bool rig_active_;
							 | 
						||
| 
								 | 
							
								  bool have_rig_;
							 | 
						||
| 
								 | 
							
								  bool rig_changed_;
							 | 
						||
| 
								 | 
							
								  TransceiverState cached_rig_state_;
							 | 
						||
| 
								 | 
							
								  int rig_resolution_;          // see Transceiver::resolution signal
							 | 
						||
| 
								 | 
							
								  double frequency_calibration_intercept_;
							 | 
						||
| 
								 | 
							
								  double frequency_calibration_slope_ppm_;
							 | 
						||
| 
								 | 
							
								  unsigned transceiver_command_number_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // configuration fields that we publish
							 | 
						||
| 
								 | 
							
								  QString my_callsign_;
							 | 
						||
| 
								 | 
							
								  QString my_grid_;
							 | 
						||
| 
								 | 
							
								  QColor color_CQ_;
							 | 
						||
| 
								 | 
							
								  QColor next_color_CQ_;
							 | 
						||
| 
								 | 
							
								  QColor color_MyCall_;
							 | 
						||
| 
								 | 
							
								  QColor next_color_MyCall_;
							 | 
						||
| 
								 | 
							
								  QColor color_TxMsg_;
							 | 
						||
| 
								 | 
							
								  QColor next_color_TxMsg_;
							 | 
						||
| 
								 | 
							
								  QColor color_DXCC_;
							 | 
						||
| 
								 | 
							
								  QColor next_color_DXCC_;
							 | 
						||
| 
								 | 
							
								  QColor color_NewCall_;
							 | 
						||
| 
								 | 
							
								  QColor next_color_NewCall_;
							 | 
						||
| 
								 | 
							
								  qint32 id_interval_;
							 | 
						||
| 
								 | 
							
								  qint32 ntrials_;
							 | 
						||
| 
								 | 
							
								  qint32 aggressive_;
							 | 
						||
| 
								 | 
							
								  qint32 RxBandwidth_;
							 | 
						||
| 
								 | 
							
								  double degrade_;
							 | 
						||
| 
								 | 
							
								  double txDelay_;
							 | 
						||
| 
								 | 
							
								  bool id_after_73_;
							 | 
						||
| 
								 | 
							
								  bool tx_QSY_allowed_;
							 | 
						||
| 
								 | 
							
								  bool spot_to_psk_reporter_;
							 | 
						||
| 
								 | 
							
								  bool monitor_off_at_startup_;
							 | 
						||
| 
								 | 
							
								  bool monitor_last_used_;
							 | 
						||
| 
								 | 
							
								  bool log_as_RTTY_;
							 | 
						||
| 
								 | 
							
								  bool report_in_comments_;
							 | 
						||
| 
								 | 
							
								  bool prompt_to_log_;
							 | 
						||
| 
								 | 
							
								  bool insert_blank_;
							 | 
						||
| 
								 | 
							
								  bool DXCC_;
							 | 
						||
| 
								 | 
							
								  bool clear_DX_;
							 | 
						||
| 
								 | 
							
								  bool miles_;
							 | 
						||
| 
								 | 
							
								  bool quick_call_;
							 | 
						||
| 
								 | 
							
								  bool disable_TX_on_73_;
							 | 
						||
| 
								 | 
							
								  int watchdog_;
							 | 
						||
| 
								 | 
							
								  bool TX_messages_;
							 | 
						||
| 
								 | 
							
								  bool enable_VHF_features_;
							 | 
						||
| 
								 | 
							
								  bool decode_at_52s_;
							 | 
						||
| 
								 | 
							
								  bool single_decode_;
							 | 
						||
| 
								 | 
							
								  bool twoPass_;
							 | 
						||
| 
								 | 
							
								  bool x2ToneSpacing_;
							 | 
						||
| 
								 | 
							
								  bool contestMode_;
							 | 
						||
| 
								 | 
							
								  bool realTimeDecode_;
							 | 
						||
| 
								 | 
							
								  QString udp_server_name_;
							 | 
						||
| 
								 | 
							
								  port_type udp_server_port_;
							 | 
						||
| 
								 | 
							
								  bool accept_udp_requests_;
							 | 
						||
| 
								 | 
							
								  bool udpWindowToFront_;
							 | 
						||
| 
								 | 
							
								  bool udpWindowRestore_;
							 | 
						||
| 
								 | 
							
								  DataMode data_mode_;
							 | 
						||
| 
								 | 
							
								  bool pwrBandTxMemory_;
							 | 
						||
| 
								 | 
							
								  bool pwrBandTuneMemory_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QAudioDeviceInfo audio_input_device_;
							 | 
						||
| 
								 | 
							
								  bool default_audio_input_device_selected_;
							 | 
						||
| 
								 | 
							
								  AudioDevice::Channel audio_input_channel_;
							 | 
						||
| 
								 | 
							
								  QAudioDeviceInfo audio_output_device_;
							 | 
						||
| 
								 | 
							
								  bool default_audio_output_device_selected_;
							 | 
						||
| 
								 | 
							
								  AudioDevice::Channel audio_output_channel_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  friend class Configuration;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "Configuration.moc"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// delegate to implementation class
							 | 
						||
| 
								 | 
							
								Configuration::Configuration (QDir const& temp_directory,
							 | 
						||
| 
								 | 
							
								                              QSettings * settings, QWidget * parent)
							 | 
						||
| 
								 | 
							
								  : m_ {this, temp_directory, settings, parent}
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Configuration::~Configuration ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QDir Configuration::doc_dir () const {return m_->doc_dir_;}
							 | 
						||
| 
								 | 
							
								QDir Configuration::data_dir () const {return m_->data_dir_;}
							 | 
						||
| 
								 | 
							
								QDir Configuration::temp_dir () const {return m_->temp_dir_;}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int Configuration::exec () {return m_->exec ();}
							 | 
						||
| 
								 | 
							
								bool Configuration::is_active () const {return m_->isVisible ();}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								QAudioDeviceInfo const& Configuration::audio_input_device () const {return m_->audio_input_device_;}
							 | 
						||
| 
								 | 
							
								AudioDevice::Channel Configuration::audio_input_channel () const {return m_->audio_input_channel_;}
							 | 
						||
| 
								 | 
							
								QAudioDeviceInfo const& Configuration::audio_output_device () const {return m_->audio_output_device_;}
							 | 
						||
| 
								 | 
							
								AudioDevice::Channel Configuration::audio_output_channel () const {return m_->audio_output_channel_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::restart_audio_input () const {return m_->restart_sound_input_device_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::restart_audio_output () const {return m_->restart_sound_output_device_;}
							 | 
						||
| 
								 | 
							
								auto Configuration::type_2_msg_gen () const -> Type2MsgGen {return m_->type_2_msg_gen_;}
							 | 
						||
| 
								 | 
							
								QString Configuration::my_callsign () const {return m_->my_callsign_;}
							 | 
						||
| 
								 | 
							
								QString Configuration::my_grid () const {return m_->my_grid_;}
							 | 
						||
| 
								 | 
							
								QColor Configuration::color_CQ () const {return m_->color_CQ_;}
							 | 
						||
| 
								 | 
							
								QColor Configuration::color_MyCall () const {return m_->color_MyCall_;}
							 | 
						||
| 
								 | 
							
								QColor Configuration::color_TxMsg () const {return m_->color_TxMsg_;}
							 | 
						||
| 
								 | 
							
								QColor Configuration::color_DXCC () const {return m_->color_DXCC_;}
							 | 
						||
| 
								 | 
							
								QColor Configuration::color_NewCall () const {return m_->color_NewCall_;}
							 | 
						||
| 
								 | 
							
								QFont Configuration::decoded_text_font () const {return m_->decoded_text_font_;}
							 | 
						||
| 
								 | 
							
								qint32 Configuration::id_interval () const {return m_->id_interval_;}
							 | 
						||
| 
								 | 
							
								qint32 Configuration::ntrials() const {return m_->ntrials_;}
							 | 
						||
| 
								 | 
							
								qint32 Configuration::aggressive() const {return m_->aggressive_;}
							 | 
						||
| 
								 | 
							
								double Configuration::degrade() const {return m_->degrade_;}
							 | 
						||
| 
								 | 
							
								double Configuration::txDelay() const {return m_->txDelay_;}
							 | 
						||
| 
								 | 
							
								qint32 Configuration::RxBandwidth() const {return m_->RxBandwidth_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::id_after_73 () const {return m_->id_after_73_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::tx_QSY_allowed () const {return m_->tx_QSY_allowed_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::spot_to_psk_reporter () const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // rig must be open and working to spot externally
							 | 
						||
| 
								 | 
							
								  return is_transceiver_online () && m_->spot_to_psk_reporter_;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								bool Configuration::monitor_off_at_startup () const {return m_->monitor_off_at_startup_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::monitor_last_used () const {return m_->rig_is_dummy_ || m_->monitor_last_used_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::log_as_RTTY () const {return m_->log_as_RTTY_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::report_in_comments () const {return m_->report_in_comments_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::prompt_to_log () const {return m_->prompt_to_log_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::insert_blank () const {return m_->insert_blank_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::DXCC () const {return m_->DXCC_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::clear_DX () const {return m_->clear_DX_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::miles () const {return m_->miles_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::quick_call () const {return m_->quick_call_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::disable_TX_on_73 () const {return m_->disable_TX_on_73_;}
							 | 
						||
| 
								 | 
							
								int Configuration::watchdog () const {return m_->watchdog_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::TX_messages () const {return m_->TX_messages_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::enable_VHF_features () const {return m_->enable_VHF_features_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::decode_at_52s () const {return m_->decode_at_52s_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::single_decode () const {return m_->single_decode_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::twoPass() const {return m_->twoPass_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::x2ToneSpacing() const {return m_->x2ToneSpacing_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::contestMode() const {return m_->contestMode_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::realTimeDecode() const {return m_->realTimeDecode_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::split_mode () const {return m_->split_mode ();}
							 | 
						||
| 
								 | 
							
								QString Configuration::udp_server_name () const {return m_->udp_server_name_;}
							 | 
						||
| 
								 | 
							
								auto Configuration::udp_server_port () const -> port_type {return m_->udp_server_port_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::accept_udp_requests () const {return m_->accept_udp_requests_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::udpWindowToFront () const {return m_->udpWindowToFront_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::udpWindowRestore () const {return m_->udpWindowRestore_;}
							 | 
						||
| 
								 | 
							
								Bands * Configuration::bands () {return &m_->bands_;}
							 | 
						||
| 
								 | 
							
								Bands const * Configuration::bands () const {return &m_->bands_;}
							 | 
						||
| 
								 | 
							
								StationList * Configuration::stations () {return &m_->stations_;}
							 | 
						||
| 
								 | 
							
								StationList const * Configuration::stations () const {return &m_->stations_;}
							 | 
						||
| 
								 | 
							
								FrequencyList * Configuration::frequencies () {return &m_->frequencies_;}
							 | 
						||
| 
								 | 
							
								FrequencyList const * Configuration::frequencies () const {return &m_->frequencies_;}
							 | 
						||
| 
								 | 
							
								QStringListModel * Configuration::macros () {return &m_->macros_;}
							 | 
						||
| 
								 | 
							
								QStringListModel const * Configuration::macros () const {return &m_->macros_;}
							 | 
						||
| 
								 | 
							
								QDir Configuration::save_directory () const {return m_->save_directory_;}
							 | 
						||
| 
								 | 
							
								QDir Configuration::azel_directory () const {return m_->azel_directory_;}
							 | 
						||
| 
								 | 
							
								QString Configuration::rig_name () const {return m_->rig_params_.rig_name;}
							 | 
						||
| 
								 | 
							
								bool Configuration::pwrBandTxMemory () const {return m_->pwrBandTxMemory_;}
							 | 
						||
| 
								 | 
							
								bool Configuration::pwrBandTuneMemory () const {return m_->pwrBandTuneMemory_;}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool Configuration::is_transceiver_online () const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return m_->rig_active_;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool Configuration::is_dummy_rig () const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return m_->rig_is_dummy_;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool Configuration::transceiver_online ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#if WSJT_TRACE_CAT
							 | 
						||
| 
								 | 
							
								  qDebug () << "Configuration::transceiver_online: " << m_->cached_rig_state_;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return m_->have_rig ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int Configuration::transceiver_resolution () const
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return m_->rig_resolution_;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::transceiver_offline ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#if WSJT_TRACE_CAT
							 | 
						||
| 
								 | 
							
								  qDebug () << "Configuration::transceiver_offline:" << m_->cached_rig_state_;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  m_->close_rig ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::transceiver_frequency (Frequency f)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#if WSJT_TRACE_CAT
							 | 
						||
| 
								 | 
							
								  qDebug () << "Configuration::transceiver_frequency:" << f << m_->cached_rig_state_;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								  m_->transceiver_frequency (f);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::transceiver_tx_frequency (Frequency f)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#if WSJT_TRACE_CAT
							 | 
						||
| 
								 | 
							
								  qDebug () << "Configuration::transceiver_tx_frequency:" << f << m_->cached_rig_state_;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  m_->transceiver_tx_frequency (f);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::transceiver_mode (MODE mode)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#if WSJT_TRACE_CAT
							 | 
						||
| 
								 | 
							
								  qDebug () << "Configuration::transceiver_mode:" << mode << m_->cached_rig_state_;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  m_->transceiver_mode (mode);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::transceiver_ptt (bool on)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#if WSJT_TRACE_CAT
							 | 
						||
| 
								 | 
							
								  qDebug () << "Configuration::transceiver_ptt:" << on << m_->cached_rig_state_;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  m_->transceiver_ptt (on);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::sync_transceiver (bool force_signal, bool enforce_mode_and_split)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#if WSJT_TRACE_CAT
							 | 
						||
| 
								 | 
							
								  qDebug () << "Configuration::sync_transceiver: force signal:" << force_signal << "enforce_mode_and_split:" << enforce_mode_and_split << m_->cached_rig_state_;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  m_->sync_transceiver (force_signal);
							 | 
						||
| 
								 | 
							
								  if (!enforce_mode_and_split)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      m_->transceiver_tx_frequency (0);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#if defined (Q_OS_MAC)
							 | 
						||
| 
								 | 
							
								  char const * app_root = "/../../../";
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								  char const * app_root = "/../";
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								  QString doc_path ()
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								#if CMAKE_BUILD
							 | 
						||
| 
								 | 
							
								    if (QDir::isRelativePath (CMAKE_INSTALL_DOCDIR))
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
									return QApplication::applicationDirPath () + app_root + CMAKE_INSTALL_DOCDIR;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    return CMAKE_INSTALL_DOCDIR;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    return QApplication::applicationDirPath ();
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QString data_path ()
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								#if CMAKE_BUILD
							 | 
						||
| 
								 | 
							
								    if (QDir::isRelativePath (CMAKE_INSTALL_DATADIR))
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
									return QApplication::applicationDirPath () + app_root + CMAKE_INSTALL_DATADIR + QChar {'/'} + CMAKE_PROJECT_NAME;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    return CMAKE_INSTALL_DATADIR;
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								    return QApplication::applicationDirPath ();
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
							 | 
						||
| 
								 | 
							
								                           QSettings * settings, QWidget * parent)
							 | 
						||
| 
								 | 
							
								  : QDialog {parent}
							 | 
						||
| 
								 | 
							
								  , self_ {self}
							 | 
						||
| 
								 | 
							
								  , ui_ {new Ui::configuration_dialog}
							 | 
						||
| 
								 | 
							
								  , settings_ {settings}
							 | 
						||
| 
								 | 
							
								  , doc_dir_ {doc_path ()}
							 | 
						||
| 
								 | 
							
								  , data_dir_ {data_path ()}
							 | 
						||
| 
								 | 
							
								  , temp_dir_ {temp_directory}
							 | 
						||
| 
								 | 
							
								  , frequencies_ {&bands_}
							 | 
						||
| 
								 | 
							
								  , next_frequencies_ {&bands_}
							 | 
						||
| 
								 | 
							
								  , stations_ {&bands_}
							 | 
						||
| 
								 | 
							
								  , next_stations_ {&bands_}
							 | 
						||
| 
								 | 
							
								  , current_offset_ {0}
							 | 
						||
| 
								 | 
							
								  , current_tx_offset_ {0}
							 | 
						||
| 
								 | 
							
								  , frequency_dialog_ {new FrequencyDialog {&modes_, this}}
							 | 
						||
| 
								 | 
							
								  , station_dialog_ {new StationDialog {&next_stations_, &bands_, this}}
							 | 
						||
| 
								 | 
							
								  , last_port_type_ {TransceiverFactory::Capabilities::none}
							 | 
						||
| 
								 | 
							
								  , rig_is_dummy_ {false}
							 | 
						||
| 
								 | 
							
								  , rig_active_ {false}
							 | 
						||
| 
								 | 
							
								  , have_rig_ {false}
							 | 
						||
| 
								 | 
							
								  , rig_changed_ {false}
							 | 
						||
| 
								 | 
							
								  , rig_resolution_ {0}
							 | 
						||
| 
								 | 
							
								  , transceiver_command_number_ {0}
							 | 
						||
| 
								 | 
							
								  , degrade_ {0.}               // initialize to zero each run, not
							 | 
						||
| 
								 | 
							
								                                // saved in settings
							 | 
						||
| 
								 | 
							
								  , default_audio_input_device_selected_ {false}
							 | 
						||
| 
								 | 
							
								  , default_audio_output_device_selected_ {false}
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  ui_->setupUi (this);
							 | 
						||
| 
								 | 
							
								//  ui_->groupBox_6->setVisible(false);              //### Temporary ??? ###
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    // Find a suitable data file location
							 | 
						||
| 
								 | 
							
								    QDir writeable_data_dir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)};
							 | 
						||
| 
								 | 
							
								    if (!writeable_data_dir.mkpath ("."))
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        MessageBox::critical_message (this, tr ("Failed to create data directory"),
							 | 
						||
| 
								 | 
							
								                                      tr ("path: \"%1\"").arg (writeable_data_dir.absolutePath ()));
							 | 
						||
| 
								 | 
							
								        throw std::runtime_error {"Failed to create data directory"};
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Make sure the default save directory exists
							 | 
						||
| 
								 | 
							
								    QString save_dir {"save"};
							 | 
						||
| 
								 | 
							
								    default_save_directory_ = writeable_data_dir;
							 | 
						||
| 
								 | 
							
								    default_azel_directory_ = writeable_data_dir;
							 | 
						||
| 
								 | 
							
								    if (!default_save_directory_.mkpath (save_dir) || !default_save_directory_.cd (save_dir))
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        MessageBox::critical_message (this, tr ("Failed to create save directory"),
							 | 
						||
| 
								 | 
							
								                                      tr ("path: \"%1\%")
							 | 
						||
| 
								 | 
							
								                                      .arg (default_save_directory_.absoluteFilePath (save_dir)));
							 | 
						||
| 
								 | 
							
								        throw std::runtime_error {"Failed to create save directory"};
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // we now have a deafult save path that exists
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // make sure samples directory exists
							 | 
						||
| 
								 | 
							
								    QString samples_dir {"samples"};
							 | 
						||
| 
								 | 
							
								    if (!default_save_directory_.mkpath (samples_dir))
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        MessageBox::critical_message (this, tr ("Failed to create samples directory"),
							 | 
						||
| 
								 | 
							
								                                      tr ("path: \"%1\"")
							 | 
						||
| 
								 | 
							
								                                      .arg (default_save_directory_.absoluteFilePath (samples_dir)));
							 | 
						||
| 
								 | 
							
								        throw std::runtime_error {"Failed to create samples directory"};
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // copy in any new sample files to the sample directory
							 | 
						||
| 
								 | 
							
								    QDir dest_dir {default_save_directory_};
							 | 
						||
| 
								 | 
							
								    dest_dir.cd (samples_dir);
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    QDir source_dir {":/" + samples_dir};
							 | 
						||
| 
								 | 
							
								    source_dir.cd (save_dir);
							 | 
						||
| 
								 | 
							
								    source_dir.cd (samples_dir);
							 | 
						||
| 
								 | 
							
								    auto list = source_dir.entryInfoList (QStringList {{"*.wav"}}, QDir::Files | QDir::Readable);
							 | 
						||
| 
								 | 
							
								    Q_FOREACH (auto const& item, list)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        if (!dest_dir.exists (item.fileName ()))
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            QFile file {item.absoluteFilePath ()};
							 | 
						||
| 
								 | 
							
								            file.copy (dest_dir.absoluteFilePath (item.fileName ()));
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // this must be done after the default paths above are set
							 | 
						||
| 
								 | 
							
								  read_settings ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // validation
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  ui_->callsign_line_edit->setValidator (new CallsignValidator {this});
							 | 
						||
| 
								 | 
							
								  ui_->grid_line_edit->setValidator (new MaidenheadLocatorValidator {this});
							 | 
						||
| 
								 | 
							
								  ui_->add_macro_line_edit->setValidator (new QRegExpValidator {message_alphabet, this});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->udp_server_port_spin_box->setMinimum (1);
							 | 
						||
| 
								 | 
							
								  ui_->udp_server_port_spin_box->setMaximum (std::numeric_limits<port_type>::max ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // assign ids to radio buttons
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  ui_->CAT_data_bits_button_group->setId (ui_->CAT_7_bit_radio_button, TransceiverFactory::seven_data_bits);
							 | 
						||
| 
								 | 
							
								  ui_->CAT_data_bits_button_group->setId (ui_->CAT_8_bit_radio_button, TransceiverFactory::eight_data_bits);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->CAT_stop_bits_button_group->setId (ui_->CAT_one_stop_bit_radio_button, TransceiverFactory::one_stop_bit);
							 | 
						||
| 
								 | 
							
								  ui_->CAT_stop_bits_button_group->setId (ui_->CAT_two_stop_bit_radio_button, TransceiverFactory::two_stop_bits);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->CAT_handshake_button_group->setId (ui_->CAT_handshake_none_radio_button, TransceiverFactory::handshake_none);
							 | 
						||
| 
								 | 
							
								  ui_->CAT_handshake_button_group->setId (ui_->CAT_handshake_xon_radio_button, TransceiverFactory::handshake_XonXoff);
							 | 
						||
| 
								 | 
							
								  ui_->CAT_handshake_button_group->setId (ui_->CAT_handshake_hardware_radio_button, TransceiverFactory::handshake_hardware);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->PTT_method_button_group->setId (ui_->PTT_VOX_radio_button, TransceiverFactory::PTT_method_VOX);
							 | 
						||
| 
								 | 
							
								  ui_->PTT_method_button_group->setId (ui_->PTT_CAT_radio_button, TransceiverFactory::PTT_method_CAT);
							 | 
						||
| 
								 | 
							
								  ui_->PTT_method_button_group->setId (ui_->PTT_DTR_radio_button, TransceiverFactory::PTT_method_DTR);
							 | 
						||
| 
								 | 
							
								  ui_->PTT_method_button_group->setId (ui_->PTT_RTS_radio_button, TransceiverFactory::PTT_method_RTS);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->TX_audio_source_button_group->setId (ui_->TX_source_mic_radio_button, TransceiverFactory::TX_audio_source_front);
							 | 
						||
| 
								 | 
							
								  ui_->TX_audio_source_button_group->setId (ui_->TX_source_data_radio_button, TransceiverFactory::TX_audio_source_rear);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->TX_mode_button_group->setId (ui_->mode_none_radio_button, data_mode_none);
							 | 
						||
| 
								 | 
							
								  ui_->TX_mode_button_group->setId (ui_->mode_USB_radio_button, data_mode_USB);
							 | 
						||
| 
								 | 
							
								  ui_->TX_mode_button_group->setId (ui_->mode_data_radio_button, data_mode_data);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->split_mode_button_group->setId (ui_->split_none_radio_button, TransceiverFactory::split_mode_none);
							 | 
						||
| 
								 | 
							
								  ui_->split_mode_button_group->setId (ui_->split_rig_radio_button, TransceiverFactory::split_mode_rig);
							 | 
						||
| 
								 | 
							
								  ui_->split_mode_button_group->setId (ui_->split_emulate_radio_button, TransceiverFactory::split_mode_emulate);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // setup PTT port combo box drop down content
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  fill_port_combo_box (ui_->PTT_port_combo_box);
							 | 
						||
| 
								 | 
							
								  ui_->PTT_port_combo_box->addItem ("CAT");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // setup hooks to keep audio channels aligned with devices
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    using namespace std;
							 | 
						||
| 
								 | 
							
								    using namespace std::placeholders;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function<void (int)> cb (bind (&Configuration::impl::update_audio_channels, this, ui_->sound_input_combo_box, _1, ui_->sound_input_channel_combo_box, false));
							 | 
						||
| 
								 | 
							
								    connect (ui_->sound_input_combo_box, static_cast<void (QComboBox::*)(int)> (&QComboBox::currentIndexChanged), cb);
							 | 
						||
| 
								 | 
							
								    cb = bind (&Configuration::impl::update_audio_channels, this, ui_->sound_output_combo_box, _1, ui_->sound_output_channel_combo_box, true);
							 | 
						||
| 
								 | 
							
								    connect (ui_->sound_output_combo_box, static_cast<void (QComboBox::*)(int)> (&QComboBox::currentIndexChanged), cb);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // setup macros list view
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  ui_->macros_list_view->setModel (&next_macros_);
							 | 
						||
| 
								 | 
							
								  ui_->macros_list_view->setItemDelegate (new MessageItemDelegate {this});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  macro_delete_action_ = new QAction {tr ("&Delete"), ui_->macros_list_view};
							 | 
						||
| 
								 | 
							
								  ui_->macros_list_view->insertAction (nullptr, macro_delete_action_);
							 | 
						||
| 
								 | 
							
								  connect (macro_delete_action_, &QAction::triggered, this, &Configuration::impl::delete_macro);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // setup working frequencies table model & view
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  frequencies_.sort (FrequencyList::frequency_column);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->frequencies_table_view->setModel (&next_frequencies_);
							 | 
						||
| 
								 | 
							
								  ui_->frequencies_table_view->sortByColumn (FrequencyList::frequency_column, Qt::AscendingOrder);
							 | 
						||
| 
								 | 
							
								  ui_->frequencies_table_view->setColumnHidden (FrequencyList::frequency_mhz_column, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // delegates
							 | 
						||
| 
								 | 
							
								  auto frequencies_item_delegate = new QStyledItemDelegate {this};
							 | 
						||
| 
								 | 
							
								  frequencies_item_delegate->setItemEditorFactory (item_editor_factory ());
							 | 
						||
| 
								 | 
							
								  ui_->frequencies_table_view->setItemDelegate (frequencies_item_delegate);
							 | 
						||
| 
								 | 
							
								  ui_->frequencies_table_view->setItemDelegateForColumn (FrequencyList::mode_column, new ForeignKeyDelegate {&modes_, 0, this});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // actions
							 | 
						||
| 
								 | 
							
								  frequency_delete_action_ = new QAction {tr ("&Delete"), ui_->frequencies_table_view};
							 | 
						||
| 
								 | 
							
								  ui_->frequencies_table_view->insertAction (nullptr, frequency_delete_action_);
							 | 
						||
| 
								 | 
							
								  connect (frequency_delete_action_, &QAction::triggered, this, &Configuration::impl::delete_frequencies);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  frequency_insert_action_ = new QAction {tr ("&Insert ..."), ui_->frequencies_table_view};
							 | 
						||
| 
								 | 
							
								  ui_->frequencies_table_view->insertAction (nullptr, frequency_insert_action_);
							 | 
						||
| 
								 | 
							
								  connect (frequency_insert_action_, &QAction::triggered, this, &Configuration::impl::insert_frequency);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // setup stations table model & view
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  stations_.sort (StationList::band_column);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->stations_table_view->setModel (&next_stations_);
							 | 
						||
| 
								 | 
							
								  ui_->stations_table_view->sortByColumn (StationList::band_column, Qt::AscendingOrder);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // delegates
							 | 
						||
| 
								 | 
							
								  auto stations_item_delegate = new QStyledItemDelegate {this};
							 | 
						||
| 
								 | 
							
								  stations_item_delegate->setItemEditorFactory (item_editor_factory ());
							 | 
						||
| 
								 | 
							
								  ui_->stations_table_view->setItemDelegate (stations_item_delegate);
							 | 
						||
| 
								 | 
							
								  ui_->stations_table_view->setItemDelegateForColumn (StationList::band_column, new ForeignKeyDelegate {&bands_, &next_stations_, 0, StationList::band_column, this});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // actions
							 | 
						||
| 
								 | 
							
								  station_delete_action_ = new QAction {tr ("&Delete"), ui_->stations_table_view};
							 | 
						||
| 
								 | 
							
								  ui_->stations_table_view->insertAction (nullptr, station_delete_action_);
							 | 
						||
| 
								 | 
							
								  connect (station_delete_action_, &QAction::triggered, this, &Configuration::impl::delete_stations);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  station_insert_action_ = new QAction {tr ("&Insert ..."), ui_->stations_table_view};
							 | 
						||
| 
								 | 
							
								  ui_->stations_table_view->insertAction (nullptr, station_insert_action_);
							 | 
						||
| 
								 | 
							
								  connect (station_insert_action_, &QAction::triggered, this, &Configuration::impl::insert_station);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // load combo boxes with audio setup choices
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  default_audio_input_device_selected_ = load_audio_devices (QAudio::AudioInput, ui_->sound_input_combo_box, &audio_input_device_);
							 | 
						||
| 
								 | 
							
								  default_audio_output_device_selected_ = load_audio_devices (QAudio::AudioOutput, ui_->sound_output_combo_box, &audio_output_device_);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  update_audio_channels (ui_->sound_input_combo_box, ui_->sound_input_combo_box->currentIndex (), ui_->sound_input_channel_combo_box, false);
							 | 
						||
| 
								 | 
							
								  update_audio_channels (ui_->sound_output_combo_box, ui_->sound_output_combo_box->currentIndex (), ui_->sound_output_channel_combo_box, true);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->sound_input_channel_combo_box->setCurrentIndex (audio_input_channel_);
							 | 
						||
| 
								 | 
							
								  ui_->sound_output_channel_combo_box->setCurrentIndex (audio_output_channel_);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  restart_sound_input_device_ = false;
							 | 
						||
| 
								 | 
							
								  restart_sound_output_device_ = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  enumerate_rigs ();
							 | 
						||
| 
								 | 
							
								  initialize_models ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  transceiver_thread_ = new QThread {this};
							 | 
						||
| 
								 | 
							
								  transceiver_thread_->start ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Configuration::impl::~impl ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  transceiver_thread_->quit ();
							 | 
						||
| 
								 | 
							
								  transceiver_thread_->wait ();
							 | 
						||
| 
								 | 
							
								  write_settings ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::initialize_models ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto pal = ui_->callsign_line_edit->palette ();
							 | 
						||
| 
								 | 
							
								  if (my_callsign_.isEmpty ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      pal.setColor (QPalette::Base, "#ffccff");
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      pal.setColor (QPalette::Base, Qt::white);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  ui_->callsign_line_edit->setPalette (pal);
							 | 
						||
| 
								 | 
							
								  ui_->grid_line_edit->setPalette (pal);
							 | 
						||
| 
								 | 
							
								  ui_->callsign_line_edit->setText (my_callsign_);
							 | 
						||
| 
								 | 
							
								  ui_->grid_line_edit->setText (my_grid_);
							 | 
						||
| 
								 | 
							
								  ui_->labCQ->setStyleSheet(QString("background: %1").arg(color_CQ_.name()));
							 | 
						||
| 
								 | 
							
								  ui_->labMyCall->setStyleSheet(QString("background: %1").arg(color_MyCall_.name()));
							 | 
						||
| 
								 | 
							
								  ui_->labTx->setStyleSheet(QString("background: %1").arg(color_TxMsg_.name()));
							 | 
						||
| 
								 | 
							
								  ui_->labDXCC->setStyleSheet(QString("background: %1").arg(color_DXCC_.name()));
							 | 
						||
| 
								 | 
							
								  ui_->labNewCall->setStyleSheet(QString("background: %1").arg(color_NewCall_.name()));
							 | 
						||
| 
								 | 
							
								  ui_->CW_id_interval_spin_box->setValue (id_interval_);  
							 | 
						||
| 
								 | 
							
								  ui_->sbNtrials->setValue (ntrials_);
							 | 
						||
| 
								 | 
							
								  ui_->sbTxDelay->setValue (txDelay_);
							 | 
						||
| 
								 | 
							
								  ui_->sbAggressive->setValue (aggressive_);
							 | 
						||
| 
								 | 
							
								  ui_->sbDegrade->setValue (degrade_);
							 | 
						||
| 
								 | 
							
								  ui_->sbBandwidth->setValue (RxBandwidth_);
							 | 
						||
| 
								 | 
							
								  ui_->PTT_method_button_group->button (rig_params_.ptt_type)->setChecked (true);
							 | 
						||
| 
								 | 
							
								  ui_->save_path_display_label->setText (save_directory_.absolutePath ());
							 | 
						||
| 
								 | 
							
								  ui_->azel_path_display_label->setText (azel_directory_.absolutePath ());
							 | 
						||
| 
								 | 
							
								  ui_->CW_id_after_73_check_box->setChecked (id_after_73_);
							 | 
						||
| 
								 | 
							
								  ui_->tx_QSY_check_box->setChecked (tx_QSY_allowed_);
							 | 
						||
| 
								 | 
							
								  ui_->psk_reporter_check_box->setChecked (spot_to_psk_reporter_);
							 | 
						||
| 
								 | 
							
								  ui_->monitor_off_check_box->setChecked (monitor_off_at_startup_);
							 | 
						||
| 
								 | 
							
								  ui_->monitor_last_used_check_box->setChecked (monitor_last_used_);
							 | 
						||
| 
								 | 
							
								  ui_->log_as_RTTY_check_box->setChecked (log_as_RTTY_);
							 | 
						||
| 
								 | 
							
								  ui_->report_in_comments_check_box->setChecked (report_in_comments_);
							 | 
						||
| 
								 | 
							
								  ui_->prompt_to_log_check_box->setChecked (prompt_to_log_);
							 | 
						||
| 
								 | 
							
								  ui_->insert_blank_check_box->setChecked (insert_blank_);
							 | 
						||
| 
								 | 
							
								  ui_->DXCC_check_box->setChecked (DXCC_);
							 | 
						||
| 
								 | 
							
								  ui_->clear_DX_check_box->setChecked (clear_DX_);
							 | 
						||
| 
								 | 
							
								  ui_->miles_check_box->setChecked (miles_);
							 | 
						||
| 
								 | 
							
								  ui_->quick_call_check_box->setChecked (quick_call_);
							 | 
						||
| 
								 | 
							
								  ui_->disable_TX_on_73_check_box->setChecked (disable_TX_on_73_);
							 | 
						||
| 
								 | 
							
								  ui_->tx_watchdog_spin_box->setValue (watchdog_);
							 | 
						||
| 
								 | 
							
								  ui_->TX_messages_check_box->setChecked (TX_messages_);
							 | 
						||
| 
								 | 
							
								  ui_->enable_VHF_features_check_box->setChecked(enable_VHF_features_);
							 | 
						||
| 
								 | 
							
								  ui_->decode_at_52s_check_box->setChecked(decode_at_52s_);
							 | 
						||
| 
								 | 
							
								  ui_->single_decode_check_box->setChecked(single_decode_);
							 | 
						||
| 
								 | 
							
								  ui_->cbTwoPass->setChecked(twoPass_);
							 | 
						||
| 
								 | 
							
								  ui_->cbx2ToneSpacing->setChecked(x2ToneSpacing_);
							 | 
						||
| 
								 | 
							
								  ui_->cbContestMode->setChecked(contestMode_);
							 | 
						||
| 
								 | 
							
								  ui_->cbRealTime->setChecked(realTimeDecode_);
							 | 
						||
| 
								 | 
							
								  ui_->cbRealTime->setVisible(false);                    //Tempoary -- probably will remove this control
							 | 
						||
| 
								 | 
							
								  ui_->type_2_msg_gen_combo_box->setCurrentIndex (type_2_msg_gen_);
							 | 
						||
| 
								 | 
							
								  ui_->rig_combo_box->setCurrentText (rig_params_.rig_name);
							 | 
						||
| 
								 | 
							
								  ui_->TX_mode_button_group->button (data_mode_)->setChecked (true);
							 | 
						||
| 
								 | 
							
								  ui_->split_mode_button_group->button (rig_params_.split_mode)->setChecked (true);
							 | 
						||
| 
								 | 
							
								  ui_->CAT_serial_baud_combo_box->setCurrentText (QString::number (rig_params_.baud));
							 | 
						||
| 
								 | 
							
								  ui_->CAT_data_bits_button_group->button (rig_params_.data_bits)->setChecked (true);
							 | 
						||
| 
								 | 
							
								  ui_->CAT_stop_bits_button_group->button (rig_params_.stop_bits)->setChecked (true);
							 | 
						||
| 
								 | 
							
								  ui_->CAT_handshake_button_group->button (rig_params_.handshake)->setChecked (true);
							 | 
						||
| 
								 | 
							
								  ui_->checkBoxPwrBandTxMemory->setChecked(pwrBandTxMemory_);
							 | 
						||
| 
								 | 
							
								  ui_->checkBoxPwrBandTuneMemory->setChecked(pwrBandTuneMemory_);
							 | 
						||
| 
								 | 
							
								  if (rig_params_.force_dtr)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      ui_->force_DTR_combo_box->setCurrentIndex (rig_params_.dtr_high ? 1 : 2);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      ui_->force_DTR_combo_box->setCurrentIndex (0);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  if (rig_params_.force_rts)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      ui_->force_RTS_combo_box->setCurrentIndex (rig_params_.rts_high ? 1 : 2);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      ui_->force_RTS_combo_box->setCurrentIndex (0);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  ui_->TX_audio_source_button_group->button (rig_params_.audio_source)->setChecked (true);
							 | 
						||
| 
								 | 
							
								  ui_->CAT_poll_interval_spin_box->setValue (rig_params_.poll_interval);
							 | 
						||
| 
								 | 
							
								  ui_->udp_server_line_edit->setText (udp_server_name_);
							 | 
						||
| 
								 | 
							
								  ui_->udp_server_port_spin_box->setValue (udp_server_port_);
							 | 
						||
| 
								 | 
							
								  ui_->accept_udp_requests_check_box->setChecked (accept_udp_requests_);
							 | 
						||
| 
								 | 
							
								  ui_->udpWindowToFront->setChecked(udpWindowToFront_);
							 | 
						||
| 
								 | 
							
								  ui_->udpWindowRestore->setChecked(udpWindowRestore_);
							 | 
						||
| 
								 | 
							
								  ui_->calibration_intercept_spin_box->setValue (frequency_calibration_intercept_);
							 | 
						||
| 
								 | 
							
								  ui_->calibration_slope_ppm_spin_box->setValue (frequency_calibration_slope_ppm_);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (rig_params_.ptt_port.isEmpty ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      if (ui_->PTT_port_combo_box->count ())
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          ui_->PTT_port_combo_box->setCurrentText (ui_->PTT_port_combo_box->itemText (0));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      ui_->PTT_port_combo_box->setCurrentText (rig_params_.ptt_port);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  next_macros_.setStringList (macros_.stringList ());
							 | 
						||
| 
								 | 
							
								  next_frequencies_.frequency_list (frequencies_.frequency_list ());
							 | 
						||
| 
								 | 
							
								  next_stations_.station_list (stations_.station_list ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::done (int r)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // do this here since window is still on screen at this point
							 | 
						||
| 
								 | 
							
								  SettingsGroup g {settings_, "Configuration"};
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("window/geometry", saveGeometry ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QDialog::done (r);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::read_settings ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  SettingsGroup g {settings_, "Configuration"};
							 | 
						||
| 
								 | 
							
								  restoreGeometry (settings_->value ("window/geometry").toByteArray ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  my_callsign_ = settings_->value ("MyCall", QString {}).toString ();
							 | 
						||
| 
								 | 
							
								  my_grid_ = settings_->value ("MyGrid", QString {}).toString ();
							 | 
						||
| 
								 | 
							
								  next_color_CQ_ = color_CQ_ = settings_->value("colorCQ","#66ff66").toString();
							 | 
						||
| 
								 | 
							
								  next_color_MyCall_ = color_MyCall_ = settings_->value("colorMyCall","#ff6666").toString();
							 | 
						||
| 
								 | 
							
								  next_color_TxMsg_ = color_TxMsg_ = settings_->value("colorTxMsg","#ffff00").toString();
							 | 
						||
| 
								 | 
							
								  next_color_DXCC_ = color_DXCC_ = settings_->value("colorDXCC","#ff00ff").toString();
							 | 
						||
| 
								 | 
							
								  next_color_NewCall_ = color_NewCall_ = settings_->value("colorNewCall","#ffaaff").toString();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (next_font_.fromString (settings_->value ("Font", QGuiApplication::font ().toString ()).toString ())
							 | 
						||
| 
								 | 
							
								      && next_font_ != font_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      font_ = next_font_;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      next_font_ = font_;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  set_application_font (font_);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (next_decoded_text_font_.fromString (settings_->value ("DecodedTextFont", "Courier, 10").toString ())
							 | 
						||
| 
								 | 
							
								      && next_decoded_text_font_ != decoded_text_font_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      decoded_text_font_ = next_decoded_text_font_;
							 | 
						||
| 
								 | 
							
								      Q_EMIT self_->decoded_text_font_changed (decoded_text_font_);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      next_decoded_text_font_ = decoded_text_font_;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  id_interval_ = settings_->value ("IDint", 0).toInt ();
							 | 
						||
| 
								 | 
							
								  ntrials_ = settings_->value ("nTrials", 6).toInt ();
							 | 
						||
| 
								 | 
							
								  txDelay_ = settings_->value ("TxDelay",0.2).toDouble();
							 | 
						||
| 
								 | 
							
								  aggressive_ = settings_->value ("Aggressive", 0).toInt ();
							 | 
						||
| 
								 | 
							
								  RxBandwidth_ = settings_->value ("RxBandwidth", 2500).toInt ();
							 | 
						||
| 
								 | 
							
								  save_directory_ = settings_->value ("SaveDir", default_save_directory_.absolutePath ()).toString ();
							 | 
						||
| 
								 | 
							
								  azel_directory_ = settings_->value ("AzElDir", default_azel_directory_.absolutePath ()).toString ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // retrieve audio input device
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    auto saved_name = settings_->value ("SoundInName").toString ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // deal with special Windows default audio devices
							 | 
						||
| 
								 | 
							
								    auto default_device = QAudioDeviceInfo::defaultInputDevice ();
							 | 
						||
| 
								 | 
							
								    if (saved_name == default_device.deviceName ())
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        audio_input_device_ = default_device;
							 | 
						||
| 
								 | 
							
								        default_audio_input_device_selected_ = true;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        default_audio_input_device_selected_ = false;
							 | 
						||
| 
								 | 
							
								        Q_FOREACH (auto const& p, QAudioDeviceInfo::availableDevices (QAudio::AudioInput)) // available audio input devices
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            if (p.deviceName () == saved_name)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								                audio_input_device_ = p;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    // retrieve audio output device
							 | 
						||
| 
								 | 
							
								    //
							 | 
						||
| 
								 | 
							
								    auto saved_name = settings_->value("SoundOutName").toString();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // deal with special Windows default audio devices
							 | 
						||
| 
								 | 
							
								    auto default_device = QAudioDeviceInfo::defaultOutputDevice ();
							 | 
						||
| 
								 | 
							
								    if (saved_name == default_device.deviceName ())
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        audio_output_device_ = default_device;
							 | 
						||
| 
								 | 
							
								        default_audio_output_device_selected_ = true;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    else
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        default_audio_output_device_selected_ = false;
							 | 
						||
| 
								 | 
							
								        Q_FOREACH (auto const& p, QAudioDeviceInfo::availableDevices (QAudio::AudioOutput)) // available audio output devices
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            if (p.deviceName () == saved_name)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								                audio_output_device_ = p;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // retrieve audio channel info
							 | 
						||
| 
								 | 
							
								  audio_input_channel_ = AudioDevice::fromString (settings_->value ("AudioInputChannel", "Mono").toString ());
							 | 
						||
| 
								 | 
							
								  audio_output_channel_ = AudioDevice::fromString (settings_->value ("AudioOutputChannel", "Mono").toString ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  type_2_msg_gen_ = settings_->value ("Type2MsgGen", QVariant::fromValue (Configuration::type_2_msg_3_full)).value<Configuration::Type2MsgGen> ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  monitor_off_at_startup_ = settings_->value ("MonitorOFF", false).toBool ();
							 | 
						||
| 
								 | 
							
								  monitor_last_used_ = settings_->value ("MonitorLastUsed", false).toBool ();
							 | 
						||
| 
								 | 
							
								  spot_to_psk_reporter_ = settings_->value ("PSKReporter", false).toBool ();
							 | 
						||
| 
								 | 
							
								  id_after_73_ = settings_->value ("After73", false).toBool ();
							 | 
						||
| 
								 | 
							
								  tx_QSY_allowed_ = settings_->value ("TxQSYAllowed", false).toBool ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  macros_.setStringList (settings_->value ("Macros", QStringList {"TNX 73 GL"}).toStringList ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (settings_->contains ("FrequenciesForModes"))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      auto const& v = settings_->value ("FrequenciesForModes");
							 | 
						||
| 
								 | 
							
								      if (v.isValid ())
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          frequencies_.frequency_list (v.value<FrequencyList::FrequencyItems> ());
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          frequencies_.reset_to_defaults ();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      frequencies_.reset_to_defaults ();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  stations_.station_list (settings_->value ("stations").value<StationList::Stations> ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  log_as_RTTY_ = settings_->value ("toRTTY", false).toBool ();
							 | 
						||
| 
								 | 
							
								  report_in_comments_ = settings_->value("dBtoComments", false).toBool ();
							 | 
						||
| 
								 | 
							
								  rig_params_.rig_name = settings_->value ("Rig", TransceiverFactory::basic_transceiver_name_).toString ();
							 | 
						||
| 
								 | 
							
								  rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name;
							 | 
						||
| 
								 | 
							
								  rig_params_.network_port = settings_->value ("CATNetworkPort").toString ();
							 | 
						||
| 
								 | 
							
								  rig_params_.usb_port = settings_->value ("CATUSBPort").toString ();
							 | 
						||
| 
								 | 
							
								  rig_params_.serial_port = settings_->value ("CATSerialPort").toString ();
							 | 
						||
| 
								 | 
							
								  rig_params_.baud = settings_->value ("CATSerialRate", 4800).toInt ();
							 | 
						||
| 
								 | 
							
								  rig_params_.data_bits = settings_->value ("CATDataBits", QVariant::fromValue (TransceiverFactory::eight_data_bits)).value<TransceiverFactory::DataBits> ();
							 | 
						||
| 
								 | 
							
								  rig_params_.stop_bits = settings_->value ("CATStopBits", QVariant::fromValue (TransceiverFactory::two_stop_bits)).value<TransceiverFactory::StopBits> ();
							 | 
						||
| 
								 | 
							
								  rig_params_.handshake = settings_->value ("CATHandshake", QVariant::fromValue (TransceiverFactory::handshake_none)).value<TransceiverFactory::Handshake> ();
							 | 
						||
| 
								 | 
							
								  rig_params_.force_dtr = settings_->value ("CATForceDTR", false).toBool ();
							 | 
						||
| 
								 | 
							
								  rig_params_.dtr_high = settings_->value ("DTR", false).toBool ();
							 | 
						||
| 
								 | 
							
								  rig_params_.force_rts = settings_->value ("CATForceRTS", false).toBool ();
							 | 
						||
| 
								 | 
							
								  rig_params_.rts_high = settings_->value ("RTS", false).toBool ();
							 | 
						||
| 
								 | 
							
								  rig_params_.ptt_type = settings_->value ("PTTMethod", QVariant::fromValue (TransceiverFactory::PTT_method_VOX)).value<TransceiverFactory::PTTMethod> ();
							 | 
						||
| 
								 | 
							
								  rig_params_.audio_source = settings_->value ("TXAudioSource", QVariant::fromValue (TransceiverFactory::TX_audio_source_front)).value<TransceiverFactory::TXAudioSource> ();
							 | 
						||
| 
								 | 
							
								  rig_params_.ptt_port = settings_->value ("PTTport").toString ();
							 | 
						||
| 
								 | 
							
								  data_mode_ = settings_->value ("DataMode", QVariant::fromValue (data_mode_none)).value<Configuration::DataMode> ();
							 | 
						||
| 
								 | 
							
								  prompt_to_log_ = settings_->value ("PromptToLog", false).toBool ();
							 | 
						||
| 
								 | 
							
								  insert_blank_ = settings_->value ("InsertBlank", false).toBool ();
							 | 
						||
| 
								 | 
							
								  DXCC_ = settings_->value ("DXCCEntity", false).toBool ();
							 | 
						||
| 
								 | 
							
								  clear_DX_ = settings_->value ("ClearCallGrid", false).toBool ();
							 | 
						||
| 
								 | 
							
								  miles_ = settings_->value ("Miles", false).toBool ();
							 | 
						||
| 
								 | 
							
								  quick_call_ = settings_->value ("QuickCall", false).toBool ();
							 | 
						||
| 
								 | 
							
								  disable_TX_on_73_ = settings_->value ("73TxDisable", false).toBool ();
							 | 
						||
| 
								 | 
							
								  watchdog_ = settings_->value ("TxWatchdog", 6).toInt ();
							 | 
						||
| 
								 | 
							
								  TX_messages_ = settings_->value ("Tx2QSO", true).toBool ();
							 | 
						||
| 
								 | 
							
								  enable_VHF_features_ = settings_->value("VHFUHF",false).toBool ();
							 | 
						||
| 
								 | 
							
								  decode_at_52s_ = settings_->value("Decode52",false).toBool ();
							 | 
						||
| 
								 | 
							
								  single_decode_ = settings_->value("SingleDecode",false).toBool ();
							 | 
						||
| 
								 | 
							
								  twoPass_ = settings_->value("TwoPass",true).toBool ();
							 | 
						||
| 
								 | 
							
								  x2ToneSpacing_ = settings_->value("x2ToneSpacing",false).toBool ();
							 | 
						||
| 
								 | 
							
								  contestMode_ = settings_->value("ContestMode",false).toBool ();
							 | 
						||
| 
								 | 
							
								  realTimeDecode_ = settings_->value("RealTimeDecode",false).toBool ();
							 | 
						||
| 
								 | 
							
								  rig_params_.poll_interval = settings_->value ("Polling", 0).toInt ();
							 | 
						||
| 
								 | 
							
								  rig_params_.split_mode = settings_->value ("SplitMode", QVariant::fromValue (TransceiverFactory::split_mode_none)).value<TransceiverFactory::SplitMode> ();
							 | 
						||
| 
								 | 
							
								  udp_server_name_ = settings_->value ("UDPServer", "127.0.0.1").toString ();
							 | 
						||
| 
								 | 
							
								  udp_server_port_ = settings_->value ("UDPServerPort", 2237).toUInt ();
							 | 
						||
| 
								 | 
							
								  accept_udp_requests_ = settings_->value ("AcceptUDPRequests", false).toBool ();
							 | 
						||
| 
								 | 
							
								  udpWindowToFront_ = settings_->value ("udpWindowToFront",false).toBool ();
							 | 
						||
| 
								 | 
							
								  udpWindowRestore_ = settings_->value ("udpWindowRestore",false).toBool ();
							 | 
						||
| 
								 | 
							
								  frequency_calibration_intercept_ = settings_->value ("CalibrationIntercept", 0.).toDouble ();
							 | 
						||
| 
								 | 
							
								  frequency_calibration_slope_ppm_ = settings_->value ("CalibrationSlopePPM", 0.).toDouble ();
							 | 
						||
| 
								 | 
							
								  pwrBandTxMemory_ = settings_->value("pwrBandTxMemory",false).toBool ();
							 | 
						||
| 
								 | 
							
								  pwrBandTuneMemory_ = settings_->value("pwrBandTuneMemory",false).toBool ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::write_settings ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  SettingsGroup g {settings_, "Configuration"};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("MyCall", my_callsign_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("MyGrid", my_grid_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue("colorCQ",color_CQ_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue("colorMyCall",color_MyCall_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue("colorTxMsg",color_TxMsg_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue("colorDXCC",color_DXCC_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue("colorNewCall",color_NewCall_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("Font", font_.toString ());
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("DecodedTextFont", decoded_text_font_.toString ());
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("IDint", id_interval_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("nTrials", ntrials_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("TxDelay", txDelay_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("Aggressive", aggressive_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("RxBandwidth", RxBandwidth_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("PTTMethod", QVariant::fromValue (rig_params_.ptt_type));
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("PTTport", rig_params_.ptt_port);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("SaveDir", save_directory_.absolutePath ());
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("AzElDir", azel_directory_.absolutePath ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (default_audio_input_device_selected_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      settings_->setValue ("SoundInName", QAudioDeviceInfo::defaultInputDevice ().deviceName ());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      settings_->setValue ("SoundInName", audio_input_device_.deviceName ());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (default_audio_output_device_selected_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      settings_->setValue ("SoundOutName", QAudioDeviceInfo::defaultOutputDevice ().deviceName ());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      settings_->setValue ("SoundOutName", audio_output_device_.deviceName ());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("AudioInputChannel", AudioDevice::toString (audio_input_channel_));
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("AudioOutputChannel", AudioDevice::toString (audio_output_channel_));
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("Type2MsgGen", QVariant::fromValue (type_2_msg_gen_));
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("MonitorOFF", monitor_off_at_startup_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("MonitorLastUsed", monitor_last_used_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("PSKReporter", spot_to_psk_reporter_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("After73", id_after_73_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("TxQSYAllowed", tx_QSY_allowed_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("Macros", macros_.stringList ());
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("FrequenciesForModes", QVariant::fromValue (frequencies_.frequency_list ()));
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("stations", QVariant::fromValue (stations_.station_list ()));
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("toRTTY", log_as_RTTY_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("dBtoComments", report_in_comments_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("Rig", rig_params_.rig_name);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("CATNetworkPort", rig_params_.network_port);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("CATUSBPort", rig_params_.usb_port);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("CATSerialPort", rig_params_.serial_port);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("CATSerialRate", rig_params_.baud);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("CATDataBits", QVariant::fromValue (rig_params_.data_bits));
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("CATStopBits", QVariant::fromValue (rig_params_.stop_bits));
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("CATHandshake", QVariant::fromValue (rig_params_.handshake));
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("DataMode", QVariant::fromValue (data_mode_));
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("PromptToLog", prompt_to_log_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("InsertBlank", insert_blank_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("DXCCEntity", DXCC_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("ClearCallGrid", clear_DX_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("Miles", miles_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("QuickCall", quick_call_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("73TxDisable", disable_TX_on_73_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("TxWatchdog", watchdog_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("Tx2QSO", TX_messages_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("CATForceDTR", rig_params_.force_dtr);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("DTR", rig_params_.dtr_high);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("CATForceRTS", rig_params_.force_rts);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("RTS", rig_params_.rts_high);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("TXAudioSource", QVariant::fromValue (rig_params_.audio_source));
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("Polling", rig_params_.poll_interval);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("SplitMode", QVariant::fromValue (rig_params_.split_mode));
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("VHFUHF", enable_VHF_features_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("Decode52", decode_at_52s_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("SingleDecode", single_decode_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("TwoPass", twoPass_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("x2ToneSpacing", x2ToneSpacing_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("ContestMode", contestMode_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("RealTimeDecode", realTimeDecode_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("UDPServer", udp_server_name_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("UDPServerPort", udp_server_port_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("AcceptUDPRequests", accept_udp_requests_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("udpWindowToFront", udpWindowToFront_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("udpWindowRestore", udpWindowRestore_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("CalibrationIntercept", frequency_calibration_intercept_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("CalibrationSlopePPM", frequency_calibration_slope_ppm_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("pwrBandTxMemory", pwrBandTxMemory_);
							 | 
						||
| 
								 | 
							
								  settings_->setValue ("pwrBandTuneMemory", pwrBandTuneMemory_);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::set_rig_invariants ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto const& rig = ui_->rig_combo_box->currentText ();
							 | 
						||
| 
								 | 
							
								  auto const& ptt_port = ui_->PTT_port_combo_box->currentText ();
							 | 
						||
| 
								 | 
							
								  auto ptt_method = static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  auto CAT_PTT_enabled = transceiver_factory_.has_CAT_PTT (rig);
							 | 
						||
| 
								 | 
							
								  auto CAT_indirect_serial_PTT = transceiver_factory_.has_CAT_indirect_serial_PTT (rig);
							 | 
						||
| 
								 | 
							
								  auto asynchronous_CAT = transceiver_factory_.has_asynchronous_CAT (rig);
							 | 
						||
| 
								 | 
							
								  auto is_hw_handshake = ui_->CAT_handshake_group_box->isEnabled ()
							 | 
						||
| 
								 | 
							
								    && TransceiverFactory::handshake_hardware == static_cast<TransceiverFactory::Handshake> (ui_->CAT_handshake_button_group->checkedId ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->test_CAT_push_button->setStyleSheet ({});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->CAT_poll_interval_label->setEnabled (!asynchronous_CAT);
							 | 
						||
| 
								 | 
							
								  ui_->CAT_poll_interval_spin_box->setEnabled (!asynchronous_CAT);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  auto port_type = transceiver_factory_.CAT_port_type (rig);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  bool is_serial_CAT (TransceiverFactory::Capabilities::serial == port_type);
							 | 
						||
| 
								 | 
							
								  auto const& cat_port = ui_->CAT_port_combo_box->currentText ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // only enable CAT option if transceiver has CAT PTT
							 | 
						||
| 
								 | 
							
								  ui_->PTT_CAT_radio_button->setEnabled (CAT_PTT_enabled);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  auto enable_ptt_port = TransceiverFactory::PTT_method_CAT != ptt_method && TransceiverFactory::PTT_method_VOX != ptt_method;
							 | 
						||
| 
								 | 
							
								  ui_->PTT_port_combo_box->setEnabled (enable_ptt_port);
							 | 
						||
| 
								 | 
							
								  ui_->PTT_port_label->setEnabled (enable_ptt_port);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (CAT_indirect_serial_PTT)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      ui_->PTT_port_combo_box->setItemData (ui_->PTT_port_combo_box->findText ("CAT")
							 | 
						||
| 
								 | 
							
								                                            , combo_box_item_enabled, Qt::UserRole - 1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      ui_->PTT_port_combo_box->setItemData (ui_->PTT_port_combo_box->findText ("CAT")
							 | 
						||
| 
								 | 
							
								                                            , combo_box_item_disabled, Qt::UserRole - 1);
							 | 
						||
| 
								 | 
							
								      if ("CAT" == ui_->PTT_port_combo_box->currentText () && ui_->PTT_port_combo_box->currentIndex () > 0)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          ui_->PTT_port_combo_box->setCurrentIndex (ui_->PTT_port_combo_box->currentIndex () - 1);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  ui_->PTT_RTS_radio_button->setEnabled (!(is_serial_CAT && ptt_port == cat_port && is_hw_handshake));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (TransceiverFactory::basic_transceiver_name_ == rig)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      // makes no sense with rig as "None"
							 | 
						||
| 
								 | 
							
								      ui_->monitor_last_used_check_box->setEnabled (false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      ui_->CAT_control_group_box->setEnabled (false);
							 | 
						||
| 
								 | 
							
								      ui_->test_CAT_push_button->setEnabled (false);
							 | 
						||
| 
								 | 
							
								      ui_->test_PTT_push_button->setEnabled (TransceiverFactory::PTT_method_DTR == ptt_method
							 | 
						||
| 
								 | 
							
								                                             || TransceiverFactory::PTT_method_RTS == ptt_method);
							 | 
						||
| 
								 | 
							
								      ui_->TX_audio_source_group_box->setEnabled (false);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      ui_->monitor_last_used_check_box->setEnabled (true);
							 | 
						||
| 
								 | 
							
								      ui_->CAT_control_group_box->setEnabled (true);
							 | 
						||
| 
								 | 
							
								      ui_->test_CAT_push_button->setEnabled (true);
							 | 
						||
| 
								 | 
							
								      ui_->test_PTT_push_button->setEnabled (false);
							 | 
						||
| 
								 | 
							
								      ui_->TX_audio_source_group_box->setEnabled (transceiver_factory_.has_CAT_PTT_mic_data (rig) && TransceiverFactory::PTT_method_CAT == ptt_method);
							 | 
						||
| 
								 | 
							
								      if (port_type != last_port_type_)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          last_port_type_ = port_type;
							 | 
						||
| 
								 | 
							
								          switch (port_type)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								            case TransceiverFactory::Capabilities::serial:
							 | 
						||
| 
								 | 
							
								              fill_port_combo_box (ui_->CAT_port_combo_box);
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->setCurrentText (rig_params_.serial_port);
							 | 
						||
| 
								 | 
							
								              if (ui_->CAT_port_combo_box->currentText ().isEmpty () && ui_->CAT_port_combo_box->count ())
							 | 
						||
| 
								 | 
							
								                {
							 | 
						||
| 
								 | 
							
								                  ui_->CAT_port_combo_box->setCurrentText (ui_->CAT_port_combo_box->itemText (0));
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_label->setText (tr ("Serial Port:"));
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->setToolTip (tr ("Serial port used for CAT control"));
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->setEnabled (true);
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case TransceiverFactory::Capabilities::network:
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->clear ();
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->setCurrentText (rig_params_.network_port);
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_label->setText (tr ("Network Server:"));
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->setToolTip (tr ("Optional hostname and port of network service.\n"
							 | 
						||
| 
								 | 
							
								                                                       "Leave blank for a sensible default on this machine.\n"
							 | 
						||
| 
								 | 
							
								                                                       "Formats:\n"
							 | 
						||
| 
								 | 
							
								                                                       "\thostname:port\n"
							 | 
						||
| 
								 | 
							
								                                                       "\tIPv4-address:port\n"
							 | 
						||
| 
								 | 
							
								                                                       "\t[IPv6-address]:port"));
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->setEnabled (true);
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            case TransceiverFactory::Capabilities::usb:
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->clear ();
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->setCurrentText (rig_params_.usb_port);
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_label->setText (tr ("USB Device:"));
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->setToolTip (tr ("Optional device identification.\n"
							 | 
						||
| 
								 | 
							
								                                                       "Leave blank for a sensible default for the rig.\n"
							 | 
						||
| 
								 | 
							
								                                                       "Format:\n"
							 | 
						||
| 
								 | 
							
								                                                       "\t[VID[:PID[:VENDOR[:PRODUCT]]]]"));
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->setEnabled (true);
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            default:
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->clear ();
							 | 
						||
| 
								 | 
							
								              ui_->CAT_port_combo_box->setEnabled (false);
							 | 
						||
| 
								 | 
							
								              break;
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      ui_->CAT_serial_port_parameters_group_box->setEnabled (is_serial_CAT);
							 | 
						||
| 
								 | 
							
								      ui_->force_DTR_combo_box->setEnabled (is_serial_CAT
							 | 
						||
| 
								 | 
							
								                                            && (cat_port != ptt_port
							 | 
						||
| 
								 | 
							
								                                                || !ui_->PTT_DTR_radio_button->isEnabled ()
							 | 
						||
| 
								 | 
							
								                                                || !ui_->PTT_DTR_radio_button->isChecked ()));
							 | 
						||
| 
								 | 
							
								      ui_->force_RTS_combo_box->setEnabled (is_serial_CAT
							 | 
						||
| 
								 | 
							
								                                            && !is_hw_handshake
							 | 
						||
| 
								 | 
							
								                                            && (cat_port != ptt_port
							 | 
						||
| 
								 | 
							
								                                                || !ui_->PTT_RTS_radio_button->isEnabled ()
							 | 
						||
| 
								 | 
							
								                                                || !ui_->PTT_RTS_radio_button->isChecked ()));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  ui_->mode_group_box->setEnabled (WSJT_RIG_NONE_CAN_SPLIT
							 | 
						||
| 
								 | 
							
								                                   || TransceiverFactory::basic_transceiver_name_ != rig);
							 | 
						||
| 
								 | 
							
								  ui_->split_operation_group_box->setEnabled (WSJT_RIG_NONE_CAN_SPLIT
							 | 
						||
| 
								 | 
							
								                                              || TransceiverFactory::basic_transceiver_name_ != rig);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool Configuration::impl::validate ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (ui_->sound_input_combo_box->currentIndex () < 0
							 | 
						||
| 
								 | 
							
								      && !QAudioDeviceInfo::availableDevices (QAudio::AudioInput).empty ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      MessageBox::critical_message (this, tr ("Invalid audio input device"));
							 | 
						||
| 
								 | 
							
								      return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (ui_->sound_output_combo_box->currentIndex () < 0
							 | 
						||
| 
								 | 
							
								      && !QAudioDeviceInfo::availableDevices (QAudio::AudioOutput).empty ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      MessageBox::critical_message (this, tr ("Invalid audio out device"));
							 | 
						||
| 
								 | 
							
								      return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!ui_->PTT_method_button_group->checkedButton ()->isEnabled ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      MessageBox::critical_message (this, tr ("Invalid PTT method"));
							 | 
						||
| 
								 | 
							
								      return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  auto ptt_method = static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ());
							 | 
						||
| 
								 | 
							
								  auto ptt_port = ui_->PTT_port_combo_box->currentText ();
							 | 
						||
| 
								 | 
							
								  if ((TransceiverFactory::PTT_method_DTR == ptt_method || TransceiverFactory::PTT_method_RTS == ptt_method)
							 | 
						||
| 
								 | 
							
								      && (ptt_port.isEmpty ()
							 | 
						||
| 
								 | 
							
								          || combo_box_item_disabled == ui_->PTT_port_combo_box->itemData (ui_->PTT_port_combo_box->findText (ptt_port), Qt::UserRole - 1)))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      MessageBox::critical_message (this, tr ("Invalid PTT port"));
							 | 
						||
| 
								 | 
							
								      return false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return true;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int Configuration::impl::exec ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // macros can be modified in the main window
							 | 
						||
| 
								 | 
							
								  next_macros_.setStringList (macros_.stringList ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  have_rig_ = rig_active_;	// record that we started with a rig open
							 | 
						||
| 
								 | 
							
								  saved_rig_params_ = rig_params_; // used to detect changes that
							 | 
						||
| 
								 | 
							
								                                   // require the Transceiver to be
							 | 
						||
| 
								 | 
							
								                                   // re-opened
							 | 
						||
| 
								 | 
							
								  rig_changed_ = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  initialize_models ();
							 | 
						||
| 
								 | 
							
								  return QDialog::exec();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								TransceiverFactory::ParameterPack Configuration::impl::gather_rig_data ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  TransceiverFactory::ParameterPack result;
							 | 
						||
| 
								 | 
							
								  result.rig_name = ui_->rig_combo_box->currentText ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  switch (transceiver_factory_.CAT_port_type (result.rig_name))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    case TransceiverFactory::Capabilities::network:
							 | 
						||
| 
								 | 
							
								      result.network_port = ui_->CAT_port_combo_box->currentText ();
							 | 
						||
| 
								 | 
							
								      result.usb_port = rig_params_.usb_port;
							 | 
						||
| 
								 | 
							
								      result.serial_port = rig_params_.serial_port;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    case TransceiverFactory::Capabilities::usb:
							 | 
						||
| 
								 | 
							
								      result.usb_port = ui_->CAT_port_combo_box->currentText ();
							 | 
						||
| 
								 | 
							
								      result.network_port = rig_params_.network_port;
							 | 
						||
| 
								 | 
							
								      result.serial_port = rig_params_.serial_port;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								      result.serial_port = ui_->CAT_port_combo_box->currentText ();
							 | 
						||
| 
								 | 
							
								      result.network_port = rig_params_.network_port;
							 | 
						||
| 
								 | 
							
								      result.usb_port = rig_params_.usb_port;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  result.baud = ui_->CAT_serial_baud_combo_box->currentText ().toInt ();
							 | 
						||
| 
								 | 
							
								  result.data_bits = static_cast<TransceiverFactory::DataBits> (ui_->CAT_data_bits_button_group->checkedId ());
							 | 
						||
| 
								 | 
							
								  result.stop_bits = static_cast<TransceiverFactory::StopBits> (ui_->CAT_stop_bits_button_group->checkedId ());
							 | 
						||
| 
								 | 
							
								  result.handshake = static_cast<TransceiverFactory::Handshake> (ui_->CAT_handshake_button_group->checkedId ());
							 | 
						||
| 
								 | 
							
								  result.force_dtr = ui_->force_DTR_combo_box->isEnabled () && ui_->force_DTR_combo_box->currentIndex () > 0;
							 | 
						||
| 
								 | 
							
								  result.dtr_high = ui_->force_DTR_combo_box->isEnabled () && 1 == ui_->force_DTR_combo_box->currentIndex ();
							 | 
						||
| 
								 | 
							
								  result.force_rts = ui_->force_RTS_combo_box->isEnabled () && ui_->force_RTS_combo_box->currentIndex () > 0;
							 | 
						||
| 
								 | 
							
								  result.rts_high = ui_->force_RTS_combo_box->isEnabled () && 1 == ui_->force_RTS_combo_box->currentIndex ();
							 | 
						||
| 
								 | 
							
								  result.poll_interval = ui_->CAT_poll_interval_spin_box->value ();
							 | 
						||
| 
								 | 
							
								  result.ptt_type = static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ());
							 | 
						||
| 
								 | 
							
								  result.ptt_port = ui_->PTT_port_combo_box->currentText ();
							 | 
						||
| 
								 | 
							
								  result.audio_source = static_cast<TransceiverFactory::TXAudioSource> (ui_->TX_audio_source_button_group->checkedId ());
							 | 
						||
| 
								 | 
							
								  result.split_mode = static_cast<TransceiverFactory::SplitMode> (ui_->split_mode_button_group->checkedId ());
							 | 
						||
| 
								 | 
							
								  return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::accept ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // Called when OK button is clicked.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!validate ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      return;			// not accepting
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // extract all rig related configuration parameters into temporary
							 | 
						||
| 
								 | 
							
								  // structure for checking if the rig needs re-opening without
							 | 
						||
| 
								 | 
							
								  // actually updating our live state
							 | 
						||
| 
								 | 
							
								  auto temp_rig_params = gather_rig_data ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // open_rig() uses values from models so we use it to validate the
							 | 
						||
| 
								 | 
							
								  // Transceiver settings before agreeing to accept the configuration
							 | 
						||
| 
								 | 
							
								  if (temp_rig_params != rig_params_ && !open_rig ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      return;			// not accepting
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QDialog::accept();            // do this before accessing custom
							 | 
						||
| 
								 | 
							
								                                // models so that any changes in
							 | 
						||
| 
								 | 
							
								                                // delegates in views get flushed to
							 | 
						||
| 
								 | 
							
								                                // the underlying models before we
							 | 
						||
| 
								 | 
							
								                                // access them
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  sync_transceiver (true);	// force an update
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								  // from here on we are bound to accept the new configuration
							 | 
						||
| 
								 | 
							
								  // parameters so extract values from models and make them live
							 | 
						||
| 
								 | 
							
								  //
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (next_font_ != font_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      font_ = next_font_;
							 | 
						||
| 
								 | 
							
								      set_application_font (font_);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (next_decoded_text_font_ != decoded_text_font_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      decoded_text_font_ = next_decoded_text_font_;
							 | 
						||
| 
								 | 
							
								      Q_EMIT self_->decoded_text_font_changed (decoded_text_font_);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  color_CQ_ = next_color_CQ_;
							 | 
						||
| 
								 | 
							
								  color_MyCall_ = next_color_MyCall_;
							 | 
						||
| 
								 | 
							
								  color_TxMsg_ = next_color_TxMsg_;
							 | 
						||
| 
								 | 
							
								  color_DXCC_ = next_color_DXCC_;
							 | 
						||
| 
								 | 
							
								  color_NewCall_ = next_color_NewCall_;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  rig_params_ = temp_rig_params; // now we can go live with the rig
							 | 
						||
| 
								 | 
							
								                                 // related configuration parameters
							 | 
						||
| 
								 | 
							
								  rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // Check to see whether SoundInThread must be restarted,
							 | 
						||
| 
								 | 
							
								  // and save user parameters.
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    auto const& device_name = ui_->sound_input_combo_box->currentText ();
							 | 
						||
| 
								 | 
							
								    if (device_name != audio_input_device_.deviceName ())
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        auto const& default_device = QAudioDeviceInfo::defaultInputDevice ();
							 | 
						||
| 
								 | 
							
								        if (device_name == default_device.deviceName ())
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            audio_input_device_ = default_device;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            bool found {false};
							 | 
						||
| 
								 | 
							
								            Q_FOREACH (auto const& d, QAudioDeviceInfo::availableDevices (QAudio::AudioInput))
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								                if (device_name == d.deviceName ())
							 | 
						||
| 
								 | 
							
								                  {
							 | 
						||
| 
								 | 
							
								                    audio_input_device_ = d;
							 | 
						||
| 
								 | 
							
								                    found = true;
							 | 
						||
| 
								 | 
							
								                  }
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (!found)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								                audio_input_device_ = default_device;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        restart_sound_input_device_ = true;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    auto const& device_name = ui_->sound_output_combo_box->currentText ();
							 | 
						||
| 
								 | 
							
								    if (device_name != audio_output_device_.deviceName ())
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        auto const& default_device = QAudioDeviceInfo::defaultOutputDevice ();
							 | 
						||
| 
								 | 
							
								        if (device_name == default_device.deviceName ())
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            audio_output_device_ = default_device;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        else
							 | 
						||
| 
								 | 
							
								          {
							 | 
						||
| 
								 | 
							
								            bool found {false};
							 | 
						||
| 
								 | 
							
								            Q_FOREACH (auto const& d, QAudioDeviceInfo::availableDevices (QAudio::AudioOutput))
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								                if (device_name == d.deviceName ())
							 | 
						||
| 
								 | 
							
								                  {
							 | 
						||
| 
								 | 
							
								                    audio_output_device_ = d;
							 | 
						||
| 
								 | 
							
								                    found = true;
							 | 
						||
| 
								 | 
							
								                  }
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            if (!found)
							 | 
						||
| 
								 | 
							
								              {
							 | 
						||
| 
								 | 
							
								                audio_output_device_ = default_device;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        restart_sound_output_device_ = true;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (audio_input_channel_ != static_cast<AudioDevice::Channel> (ui_->sound_input_channel_combo_box->currentIndex ()))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      audio_input_channel_ = static_cast<AudioDevice::Channel> (ui_->sound_input_channel_combo_box->currentIndex ());
							 | 
						||
| 
								 | 
							
								      restart_sound_input_device_ = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  Q_ASSERT (audio_input_channel_ <= AudioDevice::Right);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (audio_output_channel_ != static_cast<AudioDevice::Channel> (ui_->sound_output_channel_combo_box->currentIndex ()))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      audio_output_channel_ = static_cast<AudioDevice::Channel> (ui_->sound_output_channel_combo_box->currentIndex ());
							 | 
						||
| 
								 | 
							
								      restart_sound_output_device_ = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  Q_ASSERT (audio_output_channel_ <= AudioDevice::Both);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  my_callsign_ = ui_->callsign_line_edit->text ();
							 | 
						||
| 
								 | 
							
								  my_grid_ = ui_->grid_line_edit->text ();
							 | 
						||
| 
								 | 
							
								  spot_to_psk_reporter_ = ui_->psk_reporter_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  id_interval_ = ui_->CW_id_interval_spin_box->value ();
							 | 
						||
| 
								 | 
							
								  ntrials_ = ui_->sbNtrials->value ();
							 | 
						||
| 
								 | 
							
								  txDelay_ = ui_->sbTxDelay->value ();
							 | 
						||
| 
								 | 
							
								  aggressive_ = ui_->sbAggressive->value ();
							 | 
						||
| 
								 | 
							
								  degrade_ = ui_->sbDegrade->value ();
							 | 
						||
| 
								 | 
							
								  RxBandwidth_ = ui_->sbBandwidth->value ();
							 | 
						||
| 
								 | 
							
								  id_after_73_ = ui_->CW_id_after_73_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  tx_QSY_allowed_ = ui_->tx_QSY_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  monitor_off_at_startup_ = ui_->monitor_off_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  monitor_last_used_ = ui_->monitor_last_used_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  type_2_msg_gen_ = static_cast<Type2MsgGen> (ui_->type_2_msg_gen_combo_box->currentIndex ());
							 | 
						||
| 
								 | 
							
								  log_as_RTTY_ = ui_->log_as_RTTY_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  report_in_comments_ = ui_->report_in_comments_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  prompt_to_log_ = ui_->prompt_to_log_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  insert_blank_ = ui_->insert_blank_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  DXCC_ = ui_->DXCC_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  clear_DX_ = ui_->clear_DX_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  miles_ = ui_->miles_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  quick_call_ = ui_->quick_call_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  disable_TX_on_73_ = ui_->disable_TX_on_73_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  watchdog_ = ui_->tx_watchdog_spin_box->value ();
							 | 
						||
| 
								 | 
							
								  TX_messages_ = ui_->TX_messages_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  data_mode_ = static_cast<DataMode> (ui_->TX_mode_button_group->checkedId ());
							 | 
						||
| 
								 | 
							
								  save_directory_ = ui_->save_path_display_label->text ();
							 | 
						||
| 
								 | 
							
								  azel_directory_ = ui_->azel_path_display_label->text ();
							 | 
						||
| 
								 | 
							
								  enable_VHF_features_ = ui_->enable_VHF_features_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  decode_at_52s_ = ui_->decode_at_52s_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  single_decode_ = ui_->single_decode_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  twoPass_ = ui_->cbTwoPass->isChecked ();
							 | 
						||
| 
								 | 
							
								  x2ToneSpacing_ = ui_->cbx2ToneSpacing->isChecked ();
							 | 
						||
| 
								 | 
							
								  contestMode_ = ui_->cbContestMode->isChecked ();
							 | 
						||
| 
								 | 
							
								  realTimeDecode_ = ui_->cbRealTime->isChecked ();
							 | 
						||
| 
								 | 
							
								  frequency_calibration_intercept_ = ui_->calibration_intercept_spin_box->value ();
							 | 
						||
| 
								 | 
							
								  frequency_calibration_slope_ppm_ = ui_->calibration_slope_ppm_spin_box->value ();
							 | 
						||
| 
								 | 
							
								  pwrBandTxMemory_ = ui_->checkBoxPwrBandTxMemory->isChecked ();
							 | 
						||
| 
								 | 
							
								  pwrBandTuneMemory_ = ui_->checkBoxPwrBandTuneMemory->isChecked ();
							 | 
						||
| 
								 | 
							
								  auto new_server = ui_->udp_server_line_edit->text ();
							 | 
						||
| 
								 | 
							
								  if (new_server != udp_server_name_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      udp_server_name_ = new_server;
							 | 
						||
| 
								 | 
							
								      Q_EMIT self_->udp_server_changed (new_server);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  auto new_port = ui_->udp_server_port_spin_box->value ();
							 | 
						||
| 
								 | 
							
								  if (new_port != udp_server_port_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      udp_server_port_ = new_port;
							 | 
						||
| 
								 | 
							
								      Q_EMIT self_->udp_server_port_changed (new_port);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  
							 | 
						||
| 
								 | 
							
								  accept_udp_requests_ = ui_->accept_udp_requests_check_box->isChecked ();
							 | 
						||
| 
								 | 
							
								  udpWindowToFront_ = ui_->udpWindowToFront->isChecked ();
							 | 
						||
| 
								 | 
							
								  udpWindowRestore_ = ui_->udpWindowRestore->isChecked ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (macros_.stringList () != next_macros_.stringList ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      macros_.setStringList (next_macros_.stringList ());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (frequencies_.frequency_list () != next_frequencies_.frequency_list ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      frequencies_.frequency_list (next_frequencies_.frequency_list ());
							 | 
						||
| 
								 | 
							
								      frequencies_.sort (FrequencyList::frequency_column);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (stations_.station_list () != next_stations_.station_list ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      stations_.station_list(next_stations_.station_list ());
							 | 
						||
| 
								 | 
							
								      stations_.sort (StationList::band_column);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								 
							 | 
						||
| 
								 | 
							
								  write_settings ();		// make visible to all
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::reject ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  initialize_models ();		// reverts to settings as at exec ()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // check if the Transceiver instance changed, in which case we need
							 | 
						||
| 
								 | 
							
								  // to re open any prior Transceiver type
							 | 
						||
| 
								 | 
							
								  if (rig_changed_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      if (have_rig_)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          // we have to do this since the rig has been opened since we
							 | 
						||
| 
								 | 
							
								          // were exec'ed even though it might fail
							 | 
						||
| 
								 | 
							
								          open_rig ();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          close_rig ();
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  QDialog::reject ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_font_push_button_clicked ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  next_font_ = QFontDialog::getFont (0, next_font_, this);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_pbCQmsg_clicked()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto new_color = QColorDialog::getColor(next_color_CQ_, this, "CQ Messages Color");
							 | 
						||
| 
								 | 
							
								  if (new_color.isValid ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      next_color_CQ_ = new_color;
							 | 
						||
| 
								 | 
							
								      ui_->labCQ->setStyleSheet(QString("background: %1").arg(next_color_CQ_.name()));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_pbMyCall_clicked()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto new_color = QColorDialog::getColor(next_color_MyCall_, this, "My Call Messages Color");
							 | 
						||
| 
								 | 
							
								  if (new_color.isValid ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      next_color_MyCall_ = new_color;
							 | 
						||
| 
								 | 
							
								      ui_->labMyCall->setStyleSheet(QString("background: %1").arg(next_color_MyCall_.name()));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_pbTxMsg_clicked()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto new_color = QColorDialog::getColor(next_color_TxMsg_, this, "Tx Messages Color");
							 | 
						||
| 
								 | 
							
								  if (new_color.isValid ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      next_color_TxMsg_ = new_color;
							 | 
						||
| 
								 | 
							
								      ui_->labTx->setStyleSheet(QString("background: %1").arg(next_color_TxMsg_.name()));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_pbNewDXCC_clicked()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto new_color = QColorDialog::getColor(next_color_DXCC_, this, "New DXCC Messages Color");
							 | 
						||
| 
								 | 
							
								  if (new_color.isValid ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      next_color_DXCC_ = new_color;
							 | 
						||
| 
								 | 
							
								      ui_->labDXCC->setStyleSheet(QString("background: %1").arg(next_color_DXCC_.name()));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_pbNewCall_clicked()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto new_color = QColorDialog::getColor(next_color_NewCall_, this, "New Call Messages Color");
							 | 
						||
| 
								 | 
							
								  if (new_color.isValid ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      next_color_NewCall_ = new_color;
							 | 
						||
| 
								 | 
							
								      ui_->labNewCall->setStyleSheet(QString("background: %1").arg(next_color_NewCall_.name()));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_decoded_text_font_push_button_clicked ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  next_decoded_text_font_ = QFontDialog::getFont (0, decoded_text_font_ , this
							 | 
						||
| 
								 | 
							
								                                                  , tr ("WSJT-X Decoded Text Font Chooser")
							 | 
						||
| 
								 | 
							
								#if QT_VERSION >= 0x050201
							 | 
						||
| 
								 | 
							
								                                                  , QFontDialog::MonospacedFonts
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								                                                  );
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_PTT_port_combo_box_activated (int /* index */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_CAT_port_combo_box_activated (int /* index */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_CAT_serial_baud_combo_box_currentIndexChanged (int /* index */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_CAT_handshake_button_group_buttonClicked (int /* id */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_rig_combo_box_currentIndexChanged (int /* index */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_CAT_data_bits_button_group_buttonClicked (int /* id */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_CAT_stop_bits_button_group_buttonClicked (int /* id */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_CAT_poll_interval_spin_box_valueChanged (int /* value */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_split_mode_button_group_buttonClicked (int /* id */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_test_CAT_push_button_clicked ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (!validate ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->test_CAT_push_button->setStyleSheet ({});
							 | 
						||
| 
								 | 
							
								  if (open_rig (true))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      //Q_EMIT sync (true);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_test_PTT_push_button_clicked (bool checked)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  ui_->test_PTT_push_button->setChecked (!checked); // let status
							 | 
						||
| 
								 | 
							
								                                                    // update check us
							 | 
						||
| 
								 | 
							
								  if (!validate ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (open_rig ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      Q_EMIT self_->transceiver_ptt (checked);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_force_DTR_combo_box_currentIndexChanged (int /* index */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_force_RTS_combo_box_currentIndexChanged (int /* index */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_PTT_method_button_group_buttonClicked (int /* id */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  set_rig_invariants ();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_sound_input_combo_box_currentTextChanged (QString const& text)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  default_audio_input_device_selected_ = QAudioDeviceInfo::defaultInputDevice ().deviceName () == text;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_sound_output_combo_box_currentTextChanged (QString const& text)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  default_audio_output_device_selected_ = QAudioDeviceInfo::defaultOutputDevice ().deviceName () == text;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_add_macro_line_edit_editingFinished ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  ui_->add_macro_line_edit->setText (ui_->add_macro_line_edit->text ().toUpper ());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_delete_macro_push_button_clicked (bool /* checked */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto selection_model = ui_->macros_list_view->selectionModel ();
							 | 
						||
| 
								 | 
							
								  if (selection_model->hasSelection ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      // delete all selected items
							 | 
						||
| 
								 | 
							
								      delete_selected_macros (selection_model->selectedRows ());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::delete_macro ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto selection_model = ui_->macros_list_view->selectionModel ();
							 | 
						||
| 
								 | 
							
								  if (!selection_model->hasSelection ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      // delete item under cursor if any
							 | 
						||
| 
								 | 
							
								      auto index = selection_model->currentIndex ();
							 | 
						||
| 
								 | 
							
								      if (index.isValid ())
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          next_macros_.removeRow (index.row ());
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      // delete the whole selection
							 | 
						||
| 
								 | 
							
								      delete_selected_macros (selection_model->selectedRows ());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::delete_selected_macros (QModelIndexList selected_rows)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // sort in reverse row order so that we can delete without changing
							 | 
						||
| 
								 | 
							
								  // indices underneath us
							 | 
						||
| 
								 | 
							
								  qSort (selected_rows.begin (), selected_rows.end (), [] (QModelIndex const& lhs, QModelIndex const& rhs)
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								           return rhs.row () < lhs.row (); // reverse row ordering
							 | 
						||
| 
								 | 
							
								         });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // now delete them
							 | 
						||
| 
								 | 
							
								  Q_FOREACH (auto index, selected_rows)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      next_macros_.removeRow (index.row ());
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_add_macro_push_button_clicked (bool /* checked */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (next_macros_.insertRow (next_macros_.rowCount ()))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      auto index = next_macros_.index (next_macros_.rowCount () - 1);
							 | 
						||
| 
								 | 
							
								      ui_->macros_list_view->setCurrentIndex (index);
							 | 
						||
| 
								 | 
							
								      next_macros_.setData (index, ui_->add_macro_line_edit->text ());
							 | 
						||
| 
								 | 
							
								      ui_->add_macro_line_edit->clear ();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::delete_frequencies ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto selection_model = ui_->frequencies_table_view->selectionModel ();
							 | 
						||
| 
								 | 
							
								  selection_model->select (selection_model->selection (), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
							 | 
						||
| 
								 | 
							
								  next_frequencies_.removeDisjointRows (selection_model->selectedRows ());
							 | 
						||
| 
								 | 
							
								  ui_->frequencies_table_view->resizeColumnToContents (FrequencyList::mode_column);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_reset_frequencies_push_button_clicked (bool /* checked */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (MessageBox::Yes == MessageBox::query_message (this, tr ("Reset Working Frequencies")
							 | 
						||
| 
								 | 
							
								                                                    , tr ("Are you sure you want to discard your current "
							 | 
						||
| 
								 | 
							
								                                                          "working frequencies and replace them with default "
							 | 
						||
| 
								 | 
							
								                                                          "ones?")))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      next_frequencies_.reset_to_defaults ();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::insert_frequency ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (QDialog::Accepted == frequency_dialog_->exec ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      ui_->frequencies_table_view->setCurrentIndex (next_frequencies_.add (frequency_dialog_->item ()));
							 | 
						||
| 
								 | 
							
								      ui_->frequencies_table_view->resizeColumnToContents (FrequencyList::mode_column);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::delete_stations ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto selection_model = ui_->stations_table_view->selectionModel ();
							 | 
						||
| 
								 | 
							
								  selection_model->select (selection_model->selection (), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
							 | 
						||
| 
								 | 
							
								  next_stations_.removeDisjointRows (selection_model->selectedRows ());
							 | 
						||
| 
								 | 
							
								  ui_->stations_table_view->resizeColumnToContents (StationList::band_column);
							 | 
						||
| 
								 | 
							
								  ui_->stations_table_view->resizeColumnToContents (StationList::offset_column);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::insert_station ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (QDialog::Accepted == station_dialog_->exec ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      ui_->stations_table_view->setCurrentIndex (next_stations_.add (station_dialog_->station ()));
							 | 
						||
| 
								 | 
							
								      ui_->stations_table_view->resizeColumnToContents (StationList::band_column);
							 | 
						||
| 
								 | 
							
								      ui_->stations_table_view->resizeColumnToContents (StationList::offset_column);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_save_path_select_push_button_clicked (bool /* checked */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  QFileDialog fd {this, tr ("Save Directory"), ui_->save_path_display_label->text ()};
							 | 
						||
| 
								 | 
							
								  fd.setFileMode (QFileDialog::Directory);
							 | 
						||
| 
								 | 
							
								  fd.setOption (QFileDialog::ShowDirsOnly);
							 | 
						||
| 
								 | 
							
								  if (fd.exec ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      if (fd.selectedFiles ().size ())
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          ui_->save_path_display_label->setText (fd.selectedFiles ().at (0));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_azel_path_select_push_button_clicked (bool /* checked */)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  QFileDialog fd {this, tr ("AzEl Directory"), ui_->azel_path_display_label->text ()};
							 | 
						||
| 
								 | 
							
								  fd.setFileMode (QFileDialog::Directory);
							 | 
						||
| 
								 | 
							
								  fd.setOption (QFileDialog::ShowDirsOnly);
							 | 
						||
| 
								 | 
							
								  if (fd.exec ()) {
							 | 
						||
| 
								 | 
							
								    if (fd.selectedFiles ().size ()) {
							 | 
						||
| 
								 | 
							
								      ui_->azel_path_display_label->setText(fd.selectedFiles().at(0));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_calibration_intercept_spin_box_valueChanged (double)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  rig_active_ = false;          // force reset
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::on_calibration_slope_ppm_spin_box_valueChanged (double)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  rig_active_ = false;          // force reset
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool Configuration::impl::have_rig ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  if (!open_rig ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      MessageBox::critical_message (this, tr ("Rig control error")
							 | 
						||
| 
								 | 
							
								                                    , tr ("Failed to open connection to rig"));
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  return rig_active_;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								bool Configuration::impl::open_rig (bool force)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto result = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  auto const rig_data = gather_rig_data ();
							 | 
						||
| 
								 | 
							
								  if (force || !rig_active_ || rig_data != saved_rig_params_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      try
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          close_rig ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          // create a new Transceiver object
							 | 
						||
| 
								 | 
							
								          auto rig = transceiver_factory_.create (rig_data, transceiver_thread_);
							 | 
						||
| 
								 | 
							
								          cached_rig_state_ = Transceiver::TransceiverState {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          // hook up Configuration transceiver control signals to Transceiver slots
							 | 
						||
| 
								 | 
							
								          //
							 | 
						||
| 
								 | 
							
								          // these connections cross the thread boundary
							 | 
						||
| 
								 | 
							
								          rig_connections_ << connect (this, &Configuration::impl::set_transceiver,
							 | 
						||
| 
								 | 
							
								                                       rig.get (), &Transceiver::set);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          // hook up Transceiver signals to Configuration signals
							 | 
						||
| 
								 | 
							
								          //
							 | 
						||
| 
								 | 
							
								          // these connections cross the thread boundary
							 | 
						||
| 
								 | 
							
								          rig_connections_ << connect (rig.get (), &Transceiver::resolution, this, [=] (int resolution) {
							 | 
						||
| 
								 | 
							
								              rig_resolution_ = resolution;
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								          rig_connections_ << connect (rig.get (), &Transceiver::update, this, &Configuration::impl::handle_transceiver_update);
							 | 
						||
| 
								 | 
							
								          rig_connections_ << connect (rig.get (), &Transceiver::failure, this, &Configuration::impl::handle_transceiver_failure);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          // setup thread safe startup and close down semantics
							 | 
						||
| 
								 | 
							
								          rig_connections_ << connect (this, &Configuration::impl::start_transceiver, rig.get (), &Transceiver::start);
							 | 
						||
| 
								 | 
							
								          rig_connections_ << connect (this, &Configuration::impl::stop_transceiver, rig.get (), &Transceiver::stop);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          auto p = rig.release ();	// take ownership
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          // schedule destruction on thread quit
							 | 
						||
| 
								 | 
							
								          connect (transceiver_thread_, &QThread::finished, p, &QObject::deleteLater);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          // schedule eventual destruction for non-closing situations
							 | 
						||
| 
								 | 
							
								          //
							 | 
						||
| 
								 | 
							
								          // must   be   queued    connection   to   avoid   premature
							 | 
						||
| 
								 | 
							
								          // self-immolation  since finished  signal  is  going to  be
							 | 
						||
| 
								 | 
							
								          // emitted from  the object that  will get destroyed  in its
							 | 
						||
| 
								 | 
							
								          // own  stop  slot  i.e.  a   same  thread  signal  to  slot
							 | 
						||
| 
								 | 
							
								          // connection which by  default will be reduced  to a method
							 | 
						||
| 
								 | 
							
								          // function call.
							 | 
						||
| 
								 | 
							
								          connect (p, &Transceiver::finished, p, &Transceiver::deleteLater, Qt::QueuedConnection);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          ui_->test_CAT_push_button->setStyleSheet ({});
							 | 
						||
| 
								 | 
							
								          rig_active_ = true;
							 | 
						||
| 
								 | 
							
								          Q_EMIT start_transceiver (++transceiver_command_number_); // start rig on its thread
							 | 
						||
| 
								 | 
							
								          result = true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      catch (std::exception const& e)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          handle_transceiver_failure (e.what ());
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      saved_rig_params_ = rig_data;
							 | 
						||
| 
								 | 
							
								      rig_changed_ = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      result = true;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::set_cached_mode ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  MODE mode {Transceiver::UNK};
							 | 
						||
| 
								 | 
							
								  // override cache mode with what we want to enforce which includes
							 | 
						||
| 
								 | 
							
								  // UNK (unknown) where we want to leave the rig mode untouched
							 | 
						||
| 
								 | 
							
								  switch (data_mode_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								    case data_mode_USB: mode = Transceiver::USB; break;
							 | 
						||
| 
								 | 
							
								    case data_mode_data: mode = Transceiver::DIG_U; break;
							 | 
						||
| 
								 | 
							
								    default: break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  cached_rig_state_.mode (mode);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::transceiver_frequency (Frequency f)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  cached_rig_state_.online (true); // we want the rig online
							 | 
						||
| 
								 | 
							
								  set_cached_mode ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // apply any offset & calibration
							 | 
						||
| 
								 | 
							
								  // we store the offset here for use in feedback from the rig, we
							 | 
						||
| 
								 | 
							
								  // cannot absolutely determine if the offset should apply but by
							 | 
						||
| 
								 | 
							
								  // simply picking an offset when the Rx frequency is set and
							 | 
						||
| 
								 | 
							
								  // sticking to it we get sane behaviour
							 | 
						||
| 
								 | 
							
								  current_offset_ = stations_.offset (f);
							 | 
						||
| 
								 | 
							
								  cached_rig_state_.frequency (apply_calibration (f + current_offset_));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::transceiver_tx_frequency (Frequency f)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  Q_ASSERT (!f || split_mode ());
							 | 
						||
| 
								 | 
							
								  if (split_mode ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      cached_rig_state_.online (true); // we want the rig online
							 | 
						||
| 
								 | 
							
								      set_cached_mode ();
							 | 
						||
| 
								 | 
							
								      cached_rig_state_.split (f);
							 | 
						||
| 
								 | 
							
								      cached_rig_state_.tx_frequency (f);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // lookup offset for tx and apply calibration
							 | 
						||
| 
								 | 
							
								      if (f)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          // apply and offset and calibration
							 | 
						||
| 
								 | 
							
								          // we store the offset here for use in feedback from the
							 | 
						||
| 
								 | 
							
								          // rig, we cannot absolutely determine if the offset should
							 | 
						||
| 
								 | 
							
								          // apply but by simply picking an offset when the Rx
							 | 
						||
| 
								 | 
							
								          // frequency is set and sticking to it we get sane behaviour
							 | 
						||
| 
								 | 
							
								          current_tx_offset_ = stations_.offset (f);
							 | 
						||
| 
								 | 
							
								          cached_rig_state_.tx_frequency (apply_calibration (f + current_tx_offset_));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::transceiver_mode (MODE m)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  cached_rig_state_.online (true); // we want the rig online
							 | 
						||
| 
								 | 
							
								  cached_rig_state_.mode (m);
							 | 
						||
| 
								 | 
							
								  Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::transceiver_ptt (bool on)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  cached_rig_state_.online (true); // we want the rig online
							 | 
						||
| 
								 | 
							
								  set_cached_mode ();
							 | 
						||
| 
								 | 
							
								  cached_rig_state_.ptt (on);
							 | 
						||
| 
								 | 
							
								  Q_EMIT set_transceiver (cached_rig_state_, ++transceiver_command_number_);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::sync_transceiver (bool /*force_signal*/)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // pass this on as cache must be ignored
							 | 
						||
| 
								 | 
							
								  // Q_EMIT sync (force_signal);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::handle_transceiver_update (TransceiverState const& state,
							 | 
						||
| 
								 | 
							
								                                                     unsigned sequence_number)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#if WSJT_TRACE_CAT
							 | 
						||
| 
								 | 
							
								  qDebug () << "Configuration::handle_transceiver_update: Transceiver State #:" << sequence_number << state;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // only follow rig on some information, ignore other stuff
							 | 
						||
| 
								 | 
							
								  cached_rig_state_.online (state.online ());
							 | 
						||
| 
								 | 
							
								  cached_rig_state_.frequency (state.frequency ());
							 | 
						||
| 
								 | 
							
								  cached_rig_state_.mode (state.mode ());
							 | 
						||
| 
								 | 
							
								  cached_rig_state_.split (state.split ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (state.online ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      ui_->test_PTT_push_button->setChecked (state.ptt ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (isVisible ())
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          ui_->test_CAT_push_button->setStyleSheet ("QPushButton {background-color: green;}");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          auto const& rig = ui_->rig_combo_box->currentText ();
							 | 
						||
| 
								 | 
							
								          auto ptt_method = static_cast<TransceiverFactory::PTTMethod> (ui_->PTT_method_button_group->checkedId ());
							 | 
						||
| 
								 | 
							
								          auto CAT_PTT_enabled = transceiver_factory_.has_CAT_PTT (rig);
							 | 
						||
| 
								 | 
							
								          ui_->test_PTT_push_button->setEnabled ((TransceiverFactory::PTT_method_CAT == ptt_method && CAT_PTT_enabled)
							 | 
						||
| 
								 | 
							
								                                                 || TransceiverFactory::PTT_method_DTR == ptt_method
							 | 
						||
| 
								 | 
							
								                                                 || TransceiverFactory::PTT_method_RTS == ptt_method);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      close_rig ();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // pass on to clients if current command is processed
							 | 
						||
| 
								 | 
							
								  if (sequence_number == transceiver_command_number_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      TransceiverState reported_state {state};
							 | 
						||
| 
								 | 
							
								      // take off calibration & offset
							 | 
						||
| 
								 | 
							
								      reported_state.frequency (remove_calibration (reported_state.frequency ()) - current_offset_);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (reported_state.tx_frequency ())
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          // take off calibration & offset
							 | 
						||
| 
								 | 
							
								          reported_state.tx_frequency (remove_calibration (reported_state.tx_frequency ()) - current_tx_offset_);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      Q_EMIT self_->transceiver_update (reported_state);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::handle_transceiver_failure (QString const& reason)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								#if WSJT_TRACE_CAT
							 | 
						||
| 
								 | 
							
								  qDebug () << "Configuration::handle_transceiver_failure: reason:" << reason;
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  close_rig ();
							 | 
						||
| 
								 | 
							
								  ui_->test_PTT_push_button->setChecked (false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (isVisible ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      MessageBox::critical_message (this, tr ("Rig failure"), reason);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  else
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      // pass on if our dialog isn't active
							 | 
						||
| 
								 | 
							
								      Q_EMIT self_->transceiver_failure (reason);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::close_rig ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  ui_->test_PTT_push_button->setEnabled (false);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // revert to no rig configured
							 | 
						||
| 
								 | 
							
								  if (rig_active_)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      ui_->test_CAT_push_button->setStyleSheet ("QPushButton {background-color: red;}");
							 | 
						||
| 
								 | 
							
								      Q_EMIT stop_transceiver ();
							 | 
						||
| 
								 | 
							
								      for (auto const& connection: rig_connections_)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          disconnect (connection);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      rig_connections_.clear ();
							 | 
						||
| 
								 | 
							
								      rig_active_ = false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// load the available audio devices into the selection combo box and
							 | 
						||
| 
								 | 
							
								// select the default device if the current device isn't set or isn't
							 | 
						||
| 
								 | 
							
								// available
							 | 
						||
| 
								 | 
							
								bool Configuration::impl::load_audio_devices (QAudio::Mode mode, QComboBox * combo_box, QAudioDeviceInfo * device)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  using std::copy;
							 | 
						||
| 
								 | 
							
								  using std::back_inserter;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  bool result {false};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  combo_box->clear ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  int current_index = -1;
							 | 
						||
| 
								 | 
							
								  int default_index = -1;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  int extra_items {0};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  auto const& default_device = (mode == QAudio::AudioInput ? QAudioDeviceInfo::defaultInputDevice () : QAudioDeviceInfo::defaultOutputDevice ());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // deal with special default audio devices on Windows
							 | 
						||
| 
								 | 
							
								  if ("Default Input Device" == default_device.deviceName ()
							 | 
						||
| 
								 | 
							
								      || "Default Output Device" == default_device.deviceName ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      default_index = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      QList<QVariant> channel_counts;
							 | 
						||
| 
								 | 
							
								      auto scc = default_device.supportedChannelCounts ();
							 | 
						||
| 
								 | 
							
								      copy (scc.cbegin (), scc.cend (), back_inserter (channel_counts));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      combo_box->addItem (default_device.deviceName (), channel_counts);
							 | 
						||
| 
								 | 
							
								      ++extra_items;
							 | 
						||
| 
								 | 
							
								      if (default_device == *device)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          current_index = 0;
							 | 
						||
| 
								 | 
							
								          result = true;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Q_FOREACH (auto const& p, QAudioDeviceInfo::availableDevices (mode))
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      qDebug () << "Audio device: input:" << (QAudio::AudioInput == mode) << "name:" << p.deviceName () << "preferred format:" << p.preferredFormat () << "endians:" << p.supportedByteOrders () << "codecs:" << p.supportedCodecs () << "channels:" << p.supportedChannelCounts () << "rates:" << p.supportedSampleRates () << "sizes:" << p.supportedSampleSizes () << "types:" << p.supportedSampleTypes ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // convert supported channel counts into something we can store in the item model
							 | 
						||
| 
								 | 
							
								      QList<QVariant> channel_counts;
							 | 
						||
| 
								 | 
							
								      auto scc = p.supportedChannelCounts ();
							 | 
						||
| 
								 | 
							
								      copy (scc.cbegin (), scc.cend (), back_inserter (channel_counts));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      combo_box->addItem (p.deviceName (), channel_counts);
							 | 
						||
| 
								 | 
							
								      if (p == *device)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          current_index = combo_box->count () - 1;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else if (p == default_device)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          default_index = combo_box->count () - 1;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  if (current_index < 0)	// not found - use default
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      *device = default_device;
							 | 
						||
| 
								 | 
							
								      result = true;
							 | 
						||
| 
								 | 
							
								      current_index = default_index;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  combo_box->setCurrentIndex (current_index);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// enable only the channels that are supported by the selected audio device
							 | 
						||
| 
								 | 
							
								void Configuration::impl::update_audio_channels (QComboBox const * source_combo_box, int index, QComboBox * combo_box, bool allow_both)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // disable all items
							 | 
						||
| 
								 | 
							
								  for (int i (0); i < combo_box->count (); ++i)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      combo_box->setItemData (i, combo_box_item_disabled, Qt::UserRole - 1);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Q_FOREACH (QVariant const& v, source_combo_box->itemData (index).toList ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      // enable valid options
							 | 
						||
| 
								 | 
							
								      int n {v.toInt ()};
							 | 
						||
| 
								 | 
							
								      if (2 == n)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          combo_box->setItemData (AudioDevice::Left, combo_box_item_enabled, Qt::UserRole - 1);
							 | 
						||
| 
								 | 
							
								          combo_box->setItemData (AudioDevice::Right, combo_box_item_enabled, Qt::UserRole - 1);
							 | 
						||
| 
								 | 
							
								          if (allow_both)
							 | 
						||
| 
								 | 
							
								            {
							 | 
						||
| 
								 | 
							
								              combo_box->setItemData (AudioDevice::Both, combo_box_item_enabled, Qt::UserRole - 1);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else if (1 == n)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          combo_box->setItemData (AudioDevice::Mono, combo_box_item_enabled, Qt::UserRole - 1);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::set_application_font (QFont const& font)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  qApp->setFont (font);
							 | 
						||
| 
								 | 
							
								  // set font in the application style sheet as well in case it has
							 | 
						||
| 
								 | 
							
								  // been modified in the style sheet which has priority
							 | 
						||
| 
								 | 
							
								  qApp->setStyleSheet (qApp->styleSheet () + "* {" + font_as_stylesheet (font) + '}');
							 | 
						||
| 
								 | 
							
								  for (auto& widget : qApp->topLevelWidgets ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      widget->updateGeometry ();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// load all the supported rig names into the selection combo box
							 | 
						||
| 
								 | 
							
								void Configuration::impl::enumerate_rigs ()
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  ui_->rig_combo_box->clear ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  auto rigs = transceiver_factory_.supported_transceivers ();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (auto r = rigs.cbegin (); r != rigs.cend (); ++r)
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      if ("None" == r.key ())
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          // put None first
							 | 
						||
| 
								 | 
							
								          ui_->rig_combo_box->insertItem (0, r.key (), r.value ().model_number_);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          ui_->rig_combo_box->addItem (r.key (), r.value ().model_number_);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ui_->rig_combo_box->setCurrentText (rig_params_.rig_name);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Configuration::impl::fill_port_combo_box (QComboBox * cb)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  auto current_text = cb->currentText ();
							 | 
						||
| 
								 | 
							
								  cb->clear ();
							 | 
						||
| 
								 | 
							
								  Q_FOREACH (auto const& p, QSerialPortInfo::availablePorts ())
							 | 
						||
| 
								 | 
							
								    {
							 | 
						||
| 
								 | 
							
								      if (!p.portName ().contains ( "NULL" )) // virtual serial port pairs
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          // remove possibly confusing Windows device path (OK because
							 | 
						||
| 
								 | 
							
								          // it gets added back by Hamlib)
							 | 
						||
| 
								 | 
							
								          cb->addItem (p.systemLocation ().remove (QRegularExpression {R"(^\\\\\.\\)"}));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  cb->addItem("USB");
							 | 
						||
| 
								 | 
							
								  cb->setEditText (current_text);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								auto Configuration::impl::apply_calibration (Frequency f) const -> Frequency
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return std::llround (frequency_calibration_intercept_
							 | 
						||
| 
								 | 
							
								                       + (1. + frequency_calibration_slope_ppm_ / 1.e6) * f);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								auto Configuration::impl::remove_calibration (Frequency f) const -> Frequency
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  return std::llround ((f - frequency_calibration_intercept_)
							 | 
						||
| 
								 | 
							
								                       / (1. + frequency_calibration_slope_ppm_ / 1.e6));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if !defined (QT_NO_DEBUG_STREAM)
							 | 
						||
| 
								 | 
							
								ENUM_QDEBUG_OPS_IMPL (Configuration, DataMode);
							 | 
						||
| 
								 | 
							
								ENUM_QDEBUG_OPS_IMPL (Configuration, Type2MsgGen);
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ENUM_QDATASTREAM_OPS_IMPL (Configuration, DataMode);
							 | 
						||
| 
								 | 
							
								ENUM_QDATASTREAM_OPS_IMPL (Configuration, Type2MsgGen);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								ENUM_CONVERSION_OPS_IMPL (Configuration, DataMode);
							 | 
						||
| 
								 | 
							
								ENUM_CONVERSION_OPS_IMPL (Configuration, Type2MsgGen);
							 |