mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-03 13:30:52 -05:00 
			
		
		
		
	Add mode dependent working frequencies
Working frequencies are mode dependent and a reset to defaults button has been added. Also re-factored much of the model and item delegate code to simplify several of the model implementations. Introduced a single routine called from main to register the custom types with Qt. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@5453 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
		
							parent
							
								
									e674ac4cb0
								
							
						
					
					
						commit
						f200506571
					
				@ -1,18 +1,5 @@
 | 
			
		||||
#include "AudioDevice.hpp"
 | 
			
		||||
 | 
			
		||||
#include <QMetaType>
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
  struct init
 | 
			
		||||
  {
 | 
			
		||||
    init ()
 | 
			
		||||
    {
 | 
			
		||||
      qRegisterMetaType<AudioDevice::Channel> ("AudioDevice::Channel");
 | 
			
		||||
    }
 | 
			
		||||
  } static_initializer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool AudioDevice::initialize (OpenMode mode, Channel channel)
 | 
			
		||||
{
 | 
			
		||||
  m_channel = channel;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										87
									
								
								Bands.cpp
									
									
									
									
									
								
							
							
						
						
									
										87
									
								
								Bands.cpp
									
									
									
									
									
								
							@ -8,49 +8,43 @@
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
  // Local structure to hold a single ADIF band definition.
 | 
			
		||||
  struct ADIF_band
 | 
			
		||||
  {
 | 
			
		||||
    char const * const name_;
 | 
			
		||||
    Radio::Frequency lower_bound_;
 | 
			
		||||
    Radio::Frequency upper_bound_;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Table of ADIF band definitions as defined in the ADIF
 | 
			
		||||
  // specification.
 | 
			
		||||
  ADIF_band constexpr ADIF_bands[] = {
 | 
			
		||||
    {"2190m", 	136000u, 	137000u},
 | 
			
		||||
    {"630m", 	472000u, 	479000u},
 | 
			
		||||
    {"560m", 	501000u, 	504000u},
 | 
			
		||||
    {"160m", 	1800000u, 	2000000u},
 | 
			
		||||
    {"80m", 	3500000u, 	4000000u},
 | 
			
		||||
    {"60m", 	5102000u, 	5406500u},
 | 
			
		||||
    {"40m", 	7000000u, 	7300000u},
 | 
			
		||||
    {"30m", 	10000000u, 	10150000u},
 | 
			
		||||
    {"20m", 	14000000u, 	14350000u},
 | 
			
		||||
    {"17m", 	18068000u, 	18168000u},
 | 
			
		||||
    {"15m", 	21000000u, 	21450000u},
 | 
			
		||||
    {"12m", 	24890000u, 	24990000u},
 | 
			
		||||
    {"10m", 	28000000u, 	29700000u},
 | 
			
		||||
    {"6m", 	50000000u, 	54000000u},
 | 
			
		||||
    {"4m", 	70000000u, 	71000000u},
 | 
			
		||||
    {"2m", 	144000000u, 	148000000u},
 | 
			
		||||
    {"1.25m", 	222000000u, 	225000000u},
 | 
			
		||||
    {"70cm", 	420000000u, 	450000000u},
 | 
			
		||||
    {"33cm", 	902000000u, 	928000000u},
 | 
			
		||||
    {"23cm", 	1240000000u, 	1300000000u},
 | 
			
		||||
    {"13cm", 	2300000000u, 	2450000000u},
 | 
			
		||||
    {"9cm", 	3300000000u, 	3500000000u},
 | 
			
		||||
    {"6cm", 	5650000000u, 	5925000000u},
 | 
			
		||||
    {"3cm", 	10000000000u,	10500000000u},
 | 
			
		||||
    {"1.25cm", 	24000000000u,	24250000000u},
 | 
			
		||||
    {"6mm", 	47000000000u,	47200000000u},
 | 
			
		||||
    {"4mm", 	75500000000u,	81000000000u},
 | 
			
		||||
    {"2.5mm", 	119980000000u,	120020000000u},
 | 
			
		||||
    {"2mm", 	142000000000u,	149000000000u},
 | 
			
		||||
    {"1mm", 	241000000000u,	250000000000u},
 | 
			
		||||
  Bands::ADIFBand constexpr ADIF_bands[] = {
 | 
			
		||||
    {"2190m",	136000u,  		137000u},
 | 
			
		||||
    {"630m",  472000u,  		479000u},
 | 
			
		||||
    {"560m",  501000u,  		504000u},
 | 
			
		||||
    {"160m",  1800000u,   	2000000u},
 | 
			
		||||
    {"80m",   3500000u,   	4000000u},
 | 
			
		||||
    {"60m",   5102000u,   	5406500u},
 | 
			
		||||
    {"40m",   7000000u,   	7300000u},
 | 
			
		||||
    {"30m",   10000000u,  	10150000u},
 | 
			
		||||
    {"20m",   14000000u,  	14350000u},
 | 
			
		||||
    {"17m",   18068000u,  	18168000u},
 | 
			
		||||
    {"15m",   21000000u,  	21450000u},
 | 
			
		||||
    {"12m",   24890000u,  	24990000u},
 | 
			
		||||
    {"10m",   28000000u,  	29700000u},
 | 
			
		||||
    {"6m",  	50000000u,  	54000000u},
 | 
			
		||||
    {"4m",  	70000000u,  	71000000u},
 | 
			
		||||
    {"2m",  	144000000u,   148000000u},
 | 
			
		||||
    {"1.25m", 222000000u,   225000000u},
 | 
			
		||||
    {"70cm",  420000000u,   450000000u},
 | 
			
		||||
    {"33cm",  902000000u,   928000000u},
 | 
			
		||||
    {"23cm",  1240000000u,  1300000000u},
 | 
			
		||||
    {"13cm",  2300000000u,  2450000000u},
 | 
			
		||||
    {"9cm",   3300000000u,  3500000000u},
 | 
			
		||||
    {"6cm",   5650000000u,  5925000000u},
 | 
			
		||||
    {"3cm",   10000000000u, 10500000000u},
 | 
			
		||||
    {"1.25cm",24000000000u, 24250000000u},
 | 
			
		||||
    {"6mm",   47000000000u, 47200000000u},
 | 
			
		||||
    {"4mm",   75500000000u, 81000000000u},
 | 
			
		||||
    {"2.5mm", 119980000000u,120020000000u},
 | 
			
		||||
    {"2mm",   142000000000u,149000000000u},
 | 
			
		||||
    {"1mm",   241000000000u,250000000000u},
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  auto constexpr out_of_band = "OOB";
 | 
			
		||||
  Bands::ADIFBand constexpr oob = {"OOB", 0, std::numeric_limits<Bands::Frequency>::max ()};
 | 
			
		||||
 | 
			
		||||
  int constexpr table_rows ()
 | 
			
		||||
  {
 | 
			
		||||
@ -63,19 +57,22 @@ Bands::Bands (QObject * parent)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QModelIndex Bands::find (QVariant const& v) const
 | 
			
		||||
auto Bands::find (Frequency f) const -> ADIFBand const *
 | 
			
		||||
{
 | 
			
		||||
  auto f = v.value<Radio::Frequency> ();
 | 
			
		||||
  auto end_iter = ADIF_bands + table_rows ();
 | 
			
		||||
  auto row_iter = std::find_if (ADIF_bands, end_iter, [f] (ADIF_band const& band) {
 | 
			
		||||
  auto const& end_iter = ADIF_bands + table_rows ();
 | 
			
		||||
  auto const& row_iter = std::find_if (ADIF_bands, end_iter, [f] (ADIFBand const& band) {
 | 
			
		||||
      return band.lower_bound_ <= f && f <= band.upper_bound_;
 | 
			
		||||
    });
 | 
			
		||||
  if (row_iter != end_iter)
 | 
			
		||||
    {
 | 
			
		||||
      return index (row_iter - ADIF_bands, 0); // return the band row index
 | 
			
		||||
      return row_iter;
 | 
			
		||||
    }
 | 
			
		||||
  return &oob;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  return QModelIndex {};
 | 
			
		||||
auto Bands::out_of_band () const -> ADIFBand const *
 | 
			
		||||
{
 | 
			
		||||
  return &oob;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Bands::rowCount (QModelIndex const& parent) const
 | 
			
		||||
@ -102,7 +99,7 @@ QVariant Bands::data (QModelIndex const& index, int role) const
 | 
			
		||||
      // Hijack root for OOB string.
 | 
			
		||||
      if (Qt::DisplayRole == role)
 | 
			
		||||
        {
 | 
			
		||||
          item = out_of_band;
 | 
			
		||||
          item = oob.name_;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								Bands.hpp
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Bands.hpp
									
									
									
									
									
								
							@ -30,12 +30,22 @@ class Bands final
 | 
			
		||||
  : public QAbstractTableModel
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  using Frequency = Radio::Frequency;
 | 
			
		||||
 | 
			
		||||
  struct ADIFBand
 | 
			
		||||
  {
 | 
			
		||||
    char const * const name_;
 | 
			
		||||
    Radio::Frequency lower_bound_;
 | 
			
		||||
    Radio::Frequency upper_bound_;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  explicit Bands (QObject * parent = nullptr);
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Model API
 | 
			
		||||
  //
 | 
			
		||||
  QModelIndex find (QVariant const&) const; // find band Frequency is in
 | 
			
		||||
  ADIFBand const * find (Frequency) const; // find band Frequency is in
 | 
			
		||||
  ADIFBand const * out_of_band () const;
 | 
			
		||||
 | 
			
		||||
  // Custom role for sorting.
 | 
			
		||||
  static int constexpr SortRole = Qt::UserRole;
 | 
			
		||||
 | 
			
		||||
@ -177,11 +177,13 @@ endif (APPLE)
 | 
			
		||||
#
 | 
			
		||||
set (wsjt_qt_CXXSRCS
 | 
			
		||||
  qt_helpers.cpp
 | 
			
		||||
  MetaDataRegistry.cpp
 | 
			
		||||
  NetworkServerLookup.cpp
 | 
			
		||||
  revision_utils.cpp
 | 
			
		||||
  WFPalette.cpp
 | 
			
		||||
  Radio.cpp
 | 
			
		||||
  Bands.cpp
 | 
			
		||||
  Modes.cpp
 | 
			
		||||
  FrequencyList.cpp
 | 
			
		||||
  StationList.cpp
 | 
			
		||||
  FrequencyLineEdit.cpp
 | 
			
		||||
 | 
			
		||||
@ -8,11 +8,11 @@
 | 
			
		||||
class CandidateKeyFilter::impl final
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  explicit impl (QAbstractItemModel const * referencing_model
 | 
			
		||||
  explicit impl (int referenced_key_column
 | 
			
		||||
                 , int referenced_key_role
 | 
			
		||||
                 , QAbstractItemModel const * referencing_model
 | 
			
		||||
                 , int referencing_key_column
 | 
			
		||||
                 , int referenced_key_column
 | 
			
		||||
                 , int referencing_key_role
 | 
			
		||||
                 , int referenced_key_role)
 | 
			
		||||
                 , int referencing_key_role)
 | 
			
		||||
    : referencing_ {referencing_model}
 | 
			
		||||
    , referencing_key_column_ {referencing_key_column}
 | 
			
		||||
    , referencing_key_role_ {referencing_key_role}
 | 
			
		||||
@ -29,14 +29,25 @@ public:
 | 
			
		||||
  QModelIndex active_key_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
CandidateKeyFilter::CandidateKeyFilter (QAbstractItemModel const * referencing_model
 | 
			
		||||
                                        , QAbstractItemModel * referenced_model
 | 
			
		||||
                                        , int referencing_key_column
 | 
			
		||||
CandidateKeyFilter::CandidateKeyFilter (QAbstractItemModel * referenced_model
 | 
			
		||||
                                        , int referenced_key_column
 | 
			
		||||
                                        , int referencing_key_role
 | 
			
		||||
                                        , QObject * parent
 | 
			
		||||
                                        , int referenced_key_role)
 | 
			
		||||
  : QSortFilterProxyModel {nullptr} // ForeignKeyDelegate owns us
 | 
			
		||||
  , m_ {referencing_model, referencing_key_column, referenced_key_column, referencing_key_role, referenced_key_role}
 | 
			
		||||
  : QSortFilterProxyModel {parent}
 | 
			
		||||
  , m_ {referenced_key_column, referenced_key_role, nullptr, 0, Qt::EditRole}
 | 
			
		||||
{
 | 
			
		||||
  setSourceModel (referenced_model);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CandidateKeyFilter::CandidateKeyFilter (QAbstractItemModel * referenced_model
 | 
			
		||||
                                        , QAbstractItemModel const * referencing_model
 | 
			
		||||
                                        , int referenced_key_column
 | 
			
		||||
                                        , int referencing_key_column
 | 
			
		||||
                                        , QObject * parent
 | 
			
		||||
                                        , int referenced_key_role
 | 
			
		||||
                                        , int referencing_key_role)
 | 
			
		||||
  : QSortFilterProxyModel {parent}
 | 
			
		||||
  , m_ {referenced_key_column, referenced_key_role, referencing_model, referencing_key_column, referencing_key_role}
 | 
			
		||||
{
 | 
			
		||||
  setSourceModel (referenced_model);
 | 
			
		||||
}
 | 
			
		||||
@ -47,16 +58,24 @@ CandidateKeyFilter::~CandidateKeyFilter ()
 | 
			
		||||
 | 
			
		||||
void CandidateKeyFilter::set_active_key (QModelIndex const& index)
 | 
			
		||||
{
 | 
			
		||||
  if (index.isValid () )
 | 
			
		||||
  if (m_->referencing_)
 | 
			
		||||
    {
 | 
			
		||||
      Q_ASSERT (index.column () == m_->referencing_key_column_);
 | 
			
		||||
      m_->active_key_ = index;
 | 
			
		||||
      if (index.isValid () )
 | 
			
		||||
        {
 | 
			
		||||
          Q_ASSERT (index.column () == m_->referencing_key_column_);
 | 
			
		||||
          m_->active_key_ = index;
 | 
			
		||||
        }
 | 
			
		||||
      invalidateFilter ();
 | 
			
		||||
    }
 | 
			
		||||
  invalidateFilter ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool CandidateKeyFilter::filterAcceptsRow (int candidate_row, QModelIndex const& candidate_parent) const
 | 
			
		||||
{
 | 
			
		||||
  if (!m_->referencing_)            // many to many passes all
 | 
			
		||||
    {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  auto candidate_key = sourceModel ()->index (candidate_row, m_->referenced_key_column_, candidate_parent).data (m_->referenced_key_role_);
 | 
			
		||||
 | 
			
		||||
  // Include the current key.
 | 
			
		||||
 | 
			
		||||
@ -12,12 +12,17 @@ class CandidateKeyFilter final
 | 
			
		||||
  : public QSortFilterProxyModel
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  explicit CandidateKeyFilter (QAbstractItemModel const * referencing_model
 | 
			
		||||
                               , QAbstractItemModel * referenced_model
 | 
			
		||||
                               , int referencing_key_column = 0
 | 
			
		||||
                               , int referenced_key_column = 0
 | 
			
		||||
                               , int referencing_key_role = Qt::EditRole
 | 
			
		||||
  explicit CandidateKeyFilter (QAbstractItemModel * referenced_model
 | 
			
		||||
                               , int referenced_key_column
 | 
			
		||||
                               , QObject * parent = nullptr
 | 
			
		||||
                               , int referenced_key_role = Qt::EditRole);
 | 
			
		||||
  explicit CandidateKeyFilter (QAbstractItemModel * referenced_model
 | 
			
		||||
                               , QAbstractItemModel const * referencing_model
 | 
			
		||||
                               , int referenced_key_column
 | 
			
		||||
                               , int referencing_key_column
 | 
			
		||||
                               , QObject * parent = nullptr
 | 
			
		||||
                               , int referenced_key_role = Qt::EditRole
 | 
			
		||||
                               , int referencing_key_role = Qt::EditRole);
 | 
			
		||||
  ~CandidateKeyFilter ();
 | 
			
		||||
 | 
			
		||||
  // this key is not to be filtered, usually because we want to allow
 | 
			
		||||
 | 
			
		||||
@ -171,6 +171,7 @@
 | 
			
		||||
#include "TransceiverFactory.hpp"
 | 
			
		||||
#include "Transceiver.hpp"
 | 
			
		||||
#include "Bands.hpp"
 | 
			
		||||
#include "Modes.hpp"
 | 
			
		||||
#include "FrequencyList.hpp"
 | 
			
		||||
#include "StationList.hpp"
 | 
			
		||||
#include "NetworkServerLookup.hpp"
 | 
			
		||||
@ -182,17 +183,6 @@
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
  struct init
 | 
			
		||||
  {
 | 
			
		||||
    init ()
 | 
			
		||||
    {
 | 
			
		||||
      qRegisterMetaType<Configuration::DataMode> ("Configuration::DataMode");
 | 
			
		||||
      qRegisterMetaTypeStreamOperators<Configuration::DataMode> ("Configuration::DataMode");
 | 
			
		||||
      qRegisterMetaType<Configuration::Type2MsgGen> ("Configuration::Type2MsgGen");
 | 
			
		||||
      qRegisterMetaTypeStreamOperators<Configuration::Type2MsgGen> ("Configuration::Type2MsgGen");
 | 
			
		||||
    }
 | 
			
		||||
  } static_initializer;
 | 
			
		||||
 | 
			
		||||
  // these undocumented flag values when stored in (Qt::UserRole - 1)
 | 
			
		||||
  // of a ComboBox item model index allow the item to be enabled or
 | 
			
		||||
  // disabled
 | 
			
		||||
@ -210,14 +200,17 @@ class FrequencyDialog final
 | 
			
		||||
  : public QDialog
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  using Frequency = Radio::Frequency;
 | 
			
		||||
  using Item = FrequencyList::Item;
 | 
			
		||||
 | 
			
		||||
  explicit FrequencyDialog (QWidget * parent = nullptr)
 | 
			
		||||
  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);
 | 
			
		||||
@ -230,12 +223,13 @@ public:
 | 
			
		||||
    connect (button_box, &QDialogButtonBox::rejected, this, &FrequencyDialog::reject);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Frequency frequency () const
 | 
			
		||||
  Item item () const
 | 
			
		||||
  {
 | 
			
		||||
    return frequency_line_edit_.frequency ();
 | 
			
		||||
    return {frequency_line_edit_.frequency (), Modes::value (mode_combo_box_.currentText ())};
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  QComboBox mode_combo_box_;
 | 
			
		||||
  FrequencyLineEdit frequency_line_edit_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -249,7 +243,7 @@ class StationDialog final
 | 
			
		||||
public:
 | 
			
		||||
  explicit StationDialog (StationList const * stations, Bands * bands, QWidget * parent = nullptr)
 | 
			
		||||
    : QDialog {parent}
 | 
			
		||||
    , filtered_bands_ {new CandidateKeyFilter {stations, bands}}
 | 
			
		||||
    , filtered_bands_ {new CandidateKeyFilter {bands, stations, 0, 0}}
 | 
			
		||||
  {
 | 
			
		||||
    setWindowTitle (QApplication::applicationName () + " - " + tr ("Add Station"));
 | 
			
		||||
 | 
			
		||||
@ -311,6 +305,7 @@ public:
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Class MessageItemDelegate
 | 
			
		||||
//
 | 
			
		||||
//	Item delegate for message entry such as free text message macros.
 | 
			
		||||
@ -336,7 +331,6 @@ public:
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Internal implementation of the Configuration class.
 | 
			
		||||
class Configuration::impl final
 | 
			
		||||
  : public QDialog
 | 
			
		||||
@ -416,6 +410,7 @@ private:
 | 
			
		||||
  void delete_selected_macros (QModelIndexList);
 | 
			
		||||
  Q_SLOT void on_save_path_select_push_button_clicked (bool);
 | 
			
		||||
  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 ();
 | 
			
		||||
@ -471,6 +466,7 @@ private:
 | 
			
		||||
  QAction * macro_delete_action_;
 | 
			
		||||
 | 
			
		||||
  Bands bands_;
 | 
			
		||||
  Modes modes_;
 | 
			
		||||
  FrequencyList frequencies_;
 | 
			
		||||
  FrequencyList next_frequencies_;
 | 
			
		||||
  StationList stations_;
 | 
			
		||||
@ -697,24 +693,17 @@ void Configuration::sync_transceiver (bool force_signal, bool enforce_mode_and_s
 | 
			
		||||
  m_->sync_transceiver (force_signal);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Configuration::impl::impl (Configuration * self, QSettings * settings, QWidget * parent)
 | 
			
		||||
  : QDialog {parent}
 | 
			
		||||
  , self_ {self}
 | 
			
		||||
  , ui_ {new Ui::configuration_dialog}
 | 
			
		||||
  , settings_ {settings}
 | 
			
		||||
  , doc_dir_ {QApplication::applicationDirPath ()}
 | 
			
		||||
  , frequencies_ {
 | 
			
		||||
    { 136000, 136130, 474200, 1836600, 1838000, 3576000, 3592600, 5287200, 5357000,
 | 
			
		||||
      7038600, 7076000, 10138000, 10138700, 14076000, 14095600, 18102000, 18104600,
 | 
			
		||||
      21076000, 21094600, 24917000, 24924600, 28076000, 28124600, 50276000, 50293000,
 | 
			
		||||
      70091000, 144000000, 144489000, 222000000, 432000000, 432300000,
 | 
			
		||||
      902000000, 1296000000, 1296500000, 2301000000, 2304000000, 2320000000, 3400000000,
 | 
			
		||||
      3456000000, 5760000000,10368000000, 24048000000 }
 | 
			
		||||
    }
 | 
			
		||||
  , frequencies_ {&bands_}
 | 
			
		||||
  , next_frequencies_ {&bands_}
 | 
			
		||||
  , stations_ {&bands_}
 | 
			
		||||
  , next_stations_ {&bands_}
 | 
			
		||||
  , frequency_dialog_ {new FrequencyDialog {this}}
 | 
			
		||||
  , frequency_dialog_ {new FrequencyDialog {&modes_, this}}
 | 
			
		||||
  , station_dialog_ {new StationDialog {&next_stations_, &bands_, this}}
 | 
			
		||||
  , rig_active_ {false}
 | 
			
		||||
  , have_rig_ {false}
 | 
			
		||||
@ -891,12 +880,12 @@ Configuration::impl::impl (Configuration * self, QSettings * settings, QWidget *
 | 
			
		||||
  //
 | 
			
		||||
  // setup working frequencies table model & view
 | 
			
		||||
  //
 | 
			
		||||
  frequencies_.sort (0);
 | 
			
		||||
  frequencies_.sort (FrequencyList::frequency_column);
 | 
			
		||||
 | 
			
		||||
  ui_->frequencies_table_view->setModel (&next_frequencies_);
 | 
			
		||||
  ui_->frequencies_table_view->sortByColumn (0, Qt::AscendingOrder);
 | 
			
		||||
  ui_->frequencies_table_view->setItemDelegateForColumn (0, new FrequencyItemDelegate {&bands_, this});
 | 
			
		||||
  ui_->frequencies_table_view->setColumnHidden (1, true);
 | 
			
		||||
  ui_->frequencies_table_view->sortByColumn (FrequencyList::frequency_column, Qt::AscendingOrder);
 | 
			
		||||
  ui_->frequencies_table_view->setItemDelegateForColumn (FrequencyList::mode_column, new ForeignKeyDelegate {&modes_, 0, this});
 | 
			
		||||
  ui_->frequencies_table_view->setColumnHidden (FrequencyList::frequency_mhz_column, true);
 | 
			
		||||
 | 
			
		||||
  frequency_delete_action_ = new QAction {tr ("&Delete"), ui_->frequencies_table_view};
 | 
			
		||||
  ui_->frequencies_table_view->insertAction (nullptr, frequency_delete_action_);
 | 
			
		||||
@ -910,13 +899,11 @@ Configuration::impl::impl (Configuration * self, QSettings * settings, QWidget *
 | 
			
		||||
  //
 | 
			
		||||
  // setup stations table model & view
 | 
			
		||||
  //
 | 
			
		||||
  stations_.sort (0);
 | 
			
		||||
  stations_.sort (StationList::band_column);
 | 
			
		||||
 | 
			
		||||
  ui_->stations_table_view->setModel (&next_stations_);
 | 
			
		||||
  ui_->stations_table_view->sortByColumn (0, Qt::AscendingOrder);
 | 
			
		||||
  ui_->stations_table_view->setColumnWidth (1, 150);
 | 
			
		||||
  ui_->stations_table_view->setItemDelegateForColumn (0, new ForeignKeyDelegate {&next_stations_, &bands_, 0, 0, this});
 | 
			
		||||
  ui_->stations_table_view->setItemDelegateForColumn (1, new FrequencyDeltaItemDelegate {this});
 | 
			
		||||
  ui_->stations_table_view->sortByColumn (StationList::band_column, Qt::AscendingOrder);
 | 
			
		||||
  ui_->stations_table_view->setItemDelegateForColumn (StationList::band_column, new ForeignKeyDelegate {&bands_, &next_stations_, 0, StationList::band_column, this});
 | 
			
		||||
 | 
			
		||||
  station_delete_action_ = new QAction {tr ("&Delete"), ui_->stations_table_view};
 | 
			
		||||
  ui_->stations_table_view->insertAction (nullptr, station_delete_action_);
 | 
			
		||||
@ -1041,8 +1028,8 @@ void Configuration::impl::initialize_models ()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  next_macros_.setStringList (macros_.stringList ());
 | 
			
		||||
  next_frequencies_ = frequencies_.frequencies ();
 | 
			
		||||
  next_stations_ = stations_.stations ();
 | 
			
		||||
  next_frequencies_.frequency_list (frequencies_.frequency_list ());
 | 
			
		||||
  next_stations_.station_list (stations_.station_list ());
 | 
			
		||||
 | 
			
		||||
  set_rig_invariants ();
 | 
			
		||||
}
 | 
			
		||||
@ -1170,10 +1157,10 @@ void Configuration::impl::read_settings ()
 | 
			
		||||
 | 
			
		||||
  if (settings_->contains ("frequencies"))
 | 
			
		||||
    {
 | 
			
		||||
      frequencies_ = settings_->value ("frequencies").value<Radio::Frequencies> ();
 | 
			
		||||
      frequencies_.frequency_list (settings_->value ("frequencies").value<FrequencyList::FrequencyItems> ());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  stations_ = settings_->value ("stations").value<StationList::Stations> ();
 | 
			
		||||
  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 ();
 | 
			
		||||
@ -1262,8 +1249,8 @@ void Configuration::impl::write_settings ()
 | 
			
		||||
  settings_->setValue ("After73", id_after_73_);
 | 
			
		||||
  settings_->setValue ("TxQSYAllowed", tx_QSY_allowed_);
 | 
			
		||||
  settings_->setValue ("Macros", macros_.stringList ());
 | 
			
		||||
  settings_->setValue ("frequencies", QVariant::fromValue (frequencies_.frequencies ()));
 | 
			
		||||
  settings_->setValue ("stations", QVariant::fromValue (stations_.stations ()));
 | 
			
		||||
  settings_->setValue ("frequencies", 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);
 | 
			
		||||
@ -1674,16 +1661,16 @@ void Configuration::impl::accept ()
 | 
			
		||||
      macros_.setStringList (next_macros_.stringList ());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (frequencies_.frequencies () != next_frequencies_.frequencies ())
 | 
			
		||||
  if (frequencies_.frequency_list () != next_frequencies_.frequency_list ())
 | 
			
		||||
    {
 | 
			
		||||
      frequencies_ = next_frequencies_.frequencies ();
 | 
			
		||||
      frequencies_.sort (0);
 | 
			
		||||
      frequencies_.frequency_list (next_frequencies_.frequency_list ());
 | 
			
		||||
      frequencies_.sort (FrequencyList::frequency_column);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (stations_.stations () != next_stations_.stations ())
 | 
			
		||||
  if (stations_.station_list () != next_stations_.station_list ())
 | 
			
		||||
    {
 | 
			
		||||
      stations_ = next_stations_.stations ();
 | 
			
		||||
      stations_.sort (0);
 | 
			
		||||
      stations_.station_list(next_stations_.station_list ());
 | 
			
		||||
      stations_.sort (StationList::band_column);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
  write_settings ();		// make visible to all
 | 
			
		||||
@ -1975,13 +1962,26 @@ 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 (QMessageBox::Yes == QMessageBox::question (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_->frequency ()));
 | 
			
		||||
      ui_->frequencies_table_view->setCurrentIndex (next_frequencies_.add (frequency_dialog_->item ()));
 | 
			
		||||
      ui_->frequencies_table_view->resizeColumnToContents (FrequencyList::mode_column);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1990,6 +1990,8 @@ 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 ()
 | 
			
		||||
@ -1997,6 +1999,8 @@ 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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										251
									
								
								Configuration.ui
									
									
									
									
									
								
							
							
						
						
									
										251
									
								
								Configuration.ui
									
									
									
									
									
								
							@ -1807,9 +1807,15 @@ for assessing propagation and system performance.</string>
 | 
			
		||||
         <property name="title">
 | 
			
		||||
          <string>Working Frequencies</string>
 | 
			
		||||
         </property>
 | 
			
		||||
         <layout class="QGridLayout" name="gridLayout_15">
 | 
			
		||||
          <item row="0" column="0" rowspan="2">
 | 
			
		||||
         <layout class="QHBoxLayout" name="horizontalLayout">
 | 
			
		||||
          <item>
 | 
			
		||||
           <widget class="QTableView" name="frequencies_table_view">
 | 
			
		||||
            <property name="sizePolicy">
 | 
			
		||||
             <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
 | 
			
		||||
              <horstretch>1</horstretch>
 | 
			
		||||
              <verstretch>0</verstretch>
 | 
			
		||||
             </sizepolicy>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="contextMenuPolicy">
 | 
			
		||||
             <enum>Qt::ActionsContextMenu</enum>
 | 
			
		||||
            </property>
 | 
			
		||||
@ -1836,113 +1842,128 @@ for assessing propagation and system performance.</string>
 | 
			
		||||
            </attribute>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="0" column="2">
 | 
			
		||||
           <widget class="QGroupBox" name="groupBox_3">
 | 
			
		||||
            <property name="toolTip">
 | 
			
		||||
             <string>See WSPR documentattion Appendix C for details of how to determine these factors for your radio.</string>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="title">
 | 
			
		||||
             <string>Frequency Calibration</string>
 | 
			
		||||
            </property>
 | 
			
		||||
            <layout class="QFormLayout" name="formLayout_7">
 | 
			
		||||
             <property name="fieldGrowthPolicy">
 | 
			
		||||
              <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
 | 
			
		||||
             </property>
 | 
			
		||||
             <item row="0" column="0">
 | 
			
		||||
              <widget class="QLabel" name="label_7">
 | 
			
		||||
               <property name="text">
 | 
			
		||||
                <string>Intercept:</string>
 | 
			
		||||
          <item>
 | 
			
		||||
           <layout class="QVBoxLayout" name="verticalLayout_7">
 | 
			
		||||
            <item>
 | 
			
		||||
             <layout class="QHBoxLayout" name="horizontalLayout_6">
 | 
			
		||||
              <item>
 | 
			
		||||
               <widget class="QPushButton" name="reset_frequencies_push_button">
 | 
			
		||||
                <property name="text">
 | 
			
		||||
                 <string>Reset</string>
 | 
			
		||||
                </property>
 | 
			
		||||
               </widget>
 | 
			
		||||
              </item>
 | 
			
		||||
              <item>
 | 
			
		||||
               <spacer name="horizontalSpacer_6">
 | 
			
		||||
                <property name="orientation">
 | 
			
		||||
                 <enum>Qt::Horizontal</enum>
 | 
			
		||||
                </property>
 | 
			
		||||
                <property name="sizeHint" stdset="0">
 | 
			
		||||
                 <size>
 | 
			
		||||
                  <width>40</width>
 | 
			
		||||
                  <height>20</height>
 | 
			
		||||
                 </size>
 | 
			
		||||
                </property>
 | 
			
		||||
               </spacer>
 | 
			
		||||
              </item>
 | 
			
		||||
             </layout>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item>
 | 
			
		||||
             <widget class="QGroupBox" name="groupBox_3">
 | 
			
		||||
              <property name="toolTip">
 | 
			
		||||
               <string>See WSPR documentattion Appendix C for details of how to determine these factors for your radio.</string>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="title">
 | 
			
		||||
               <string>Frequency Calibration</string>
 | 
			
		||||
              </property>
 | 
			
		||||
              <layout class="QFormLayout" name="formLayout_7">
 | 
			
		||||
               <property name="fieldGrowthPolicy">
 | 
			
		||||
                <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="buddy">
 | 
			
		||||
                <cstring>calibration_intercept_spin_box</cstring>
 | 
			
		||||
               </property>
 | 
			
		||||
              </widget>
 | 
			
		||||
             </item>
 | 
			
		||||
             <item row="0" column="1">
 | 
			
		||||
              <widget class="QDoubleSpinBox" name="calibration_intercept_spin_box">
 | 
			
		||||
               <property name="alignment">
 | 
			
		||||
                <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="suffix">
 | 
			
		||||
                <string> Hz</string>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="decimals">
 | 
			
		||||
                <number>2</number>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="minimum">
 | 
			
		||||
                <double>-99999.990000000005239</double>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="maximum">
 | 
			
		||||
                <double>99999.990000000005239</double>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="singleStep">
 | 
			
		||||
                <double>0.100000000000000</double>
 | 
			
		||||
               </property>
 | 
			
		||||
              </widget>
 | 
			
		||||
             </item>
 | 
			
		||||
             <item row="1" column="0">
 | 
			
		||||
              <widget class="QLabel" name="label_8">
 | 
			
		||||
               <property name="text">
 | 
			
		||||
                <string>Slope:</string>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="buddy">
 | 
			
		||||
                <cstring>calibration_slope_ppm_spin_box</cstring>
 | 
			
		||||
               </property>
 | 
			
		||||
              </widget>
 | 
			
		||||
             </item>
 | 
			
		||||
             <item row="1" column="1">
 | 
			
		||||
              <widget class="QDoubleSpinBox" name="calibration_slope_ppm_spin_box">
 | 
			
		||||
               <property name="alignment">
 | 
			
		||||
                <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="suffix">
 | 
			
		||||
                <string> ppm</string>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="decimals">
 | 
			
		||||
                <number>4</number>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="minimum">
 | 
			
		||||
                <double>-999.999900000000025</double>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="maximum">
 | 
			
		||||
                <double>999.999900000000025</double>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="singleStep">
 | 
			
		||||
                <double>0.100000000000000</double>
 | 
			
		||||
               </property>
 | 
			
		||||
               <property name="value">
 | 
			
		||||
                <double>0.000000000000000</double>
 | 
			
		||||
               </property>
 | 
			
		||||
              </widget>
 | 
			
		||||
             </item>
 | 
			
		||||
            </layout>
 | 
			
		||||
           </widget>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="0" column="3">
 | 
			
		||||
           <spacer name="horizontalSpacer_6">
 | 
			
		||||
            <property name="orientation">
 | 
			
		||||
             <enum>Qt::Horizontal</enum>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="sizeHint" stdset="0">
 | 
			
		||||
             <size>
 | 
			
		||||
              <width>40</width>
 | 
			
		||||
              <height>20</height>
 | 
			
		||||
             </size>
 | 
			
		||||
            </property>
 | 
			
		||||
           </spacer>
 | 
			
		||||
          </item>
 | 
			
		||||
          <item row="1" column="2">
 | 
			
		||||
           <spacer name="verticalSpacer_6">
 | 
			
		||||
            <property name="orientation">
 | 
			
		||||
             <enum>Qt::Vertical</enum>
 | 
			
		||||
            </property>
 | 
			
		||||
            <property name="sizeHint" stdset="0">
 | 
			
		||||
             <size>
 | 
			
		||||
              <width>20</width>
 | 
			
		||||
              <height>40</height>
 | 
			
		||||
             </size>
 | 
			
		||||
            </property>
 | 
			
		||||
           </spacer>
 | 
			
		||||
               <item row="0" column="0">
 | 
			
		||||
                <widget class="QLabel" name="label_7">
 | 
			
		||||
                 <property name="text">
 | 
			
		||||
                  <string>Intercept:</string>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="buddy">
 | 
			
		||||
                  <cstring>calibration_intercept_spin_box</cstring>
 | 
			
		||||
                 </property>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item row="0" column="1">
 | 
			
		||||
                <widget class="QDoubleSpinBox" name="calibration_intercept_spin_box">
 | 
			
		||||
                 <property name="alignment">
 | 
			
		||||
                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="suffix">
 | 
			
		||||
                  <string> Hz</string>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="decimals">
 | 
			
		||||
                  <number>2</number>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="minimum">
 | 
			
		||||
                  <double>-99999.990000000005239</double>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="maximum">
 | 
			
		||||
                  <double>99999.990000000005239</double>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="singleStep">
 | 
			
		||||
                  <double>0.100000000000000</double>
 | 
			
		||||
                 </property>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item row="1" column="0">
 | 
			
		||||
                <widget class="QLabel" name="label_8">
 | 
			
		||||
                 <property name="text">
 | 
			
		||||
                  <string>Slope:</string>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="buddy">
 | 
			
		||||
                  <cstring>calibration_slope_ppm_spin_box</cstring>
 | 
			
		||||
                 </property>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
               <item row="1" column="1">
 | 
			
		||||
                <widget class="QDoubleSpinBox" name="calibration_slope_ppm_spin_box">
 | 
			
		||||
                 <property name="alignment">
 | 
			
		||||
                  <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="suffix">
 | 
			
		||||
                  <string> ppm</string>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="decimals">
 | 
			
		||||
                  <number>4</number>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="minimum">
 | 
			
		||||
                  <double>-999.999900000000025</double>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="maximum">
 | 
			
		||||
                  <double>999.999900000000025</double>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="singleStep">
 | 
			
		||||
                  <double>0.100000000000000</double>
 | 
			
		||||
                 </property>
 | 
			
		||||
                 <property name="value">
 | 
			
		||||
                  <double>0.000000000000000</double>
 | 
			
		||||
                 </property>
 | 
			
		||||
                </widget>
 | 
			
		||||
               </item>
 | 
			
		||||
              </layout>
 | 
			
		||||
             </widget>
 | 
			
		||||
            </item>
 | 
			
		||||
            <item>
 | 
			
		||||
             <spacer name="verticalSpacer_6">
 | 
			
		||||
              <property name="orientation">
 | 
			
		||||
               <enum>Qt::Vertical</enum>
 | 
			
		||||
              </property>
 | 
			
		||||
              <property name="sizeHint" stdset="0">
 | 
			
		||||
               <size>
 | 
			
		||||
                <width>20</width>
 | 
			
		||||
                <height>40</height>
 | 
			
		||||
               </size>
 | 
			
		||||
              </property>
 | 
			
		||||
             </spacer>
 | 
			
		||||
            </item>
 | 
			
		||||
           </layout>
 | 
			
		||||
          </item>
 | 
			
		||||
         </layout>
 | 
			
		||||
        </widget>
 | 
			
		||||
@ -1992,6 +2013,9 @@ Right click for insert and delete options.</string>
 | 
			
		||||
            <property name="wordWrap">
 | 
			
		||||
             <bool>true</bool>
 | 
			
		||||
            </property>
 | 
			
		||||
            <attribute name="horizontalHeaderCascadingSectionResizes">
 | 
			
		||||
             <bool>true</bool>
 | 
			
		||||
            </attribute>
 | 
			
		||||
            <attribute name="horizontalHeaderStretchLastSection">
 | 
			
		||||
             <bool>true</bool>
 | 
			
		||||
            </attribute>
 | 
			
		||||
@ -2274,6 +2298,7 @@ soundcard changes</string>
 | 
			
		||||
  <tabstop>udpWindowToFront</tabstop>
 | 
			
		||||
  <tabstop>udpWindowRestore</tabstop>
 | 
			
		||||
  <tabstop>frequencies_table_view</tabstop>
 | 
			
		||||
  <tabstop>reset_frequencies_push_button</tabstop>
 | 
			
		||||
  <tabstop>calibration_intercept_spin_box</tabstop>
 | 
			
		||||
  <tabstop>calibration_slope_ppm_spin_box</tabstop>
 | 
			
		||||
  <tabstop>stations_table_view</tabstop>
 | 
			
		||||
@ -2351,12 +2376,12 @@ soundcard changes</string>
 | 
			
		||||
  </connection>
 | 
			
		||||
 </connections>
 | 
			
		||||
 <buttongroups>
 | 
			
		||||
  <buttongroup name="CAT_handshake_button_group"/>
 | 
			
		||||
  <buttongroup name="split_mode_button_group"/>
 | 
			
		||||
  <buttongroup name="CAT_data_bits_button_group"/>
 | 
			
		||||
  <buttongroup name="CAT_stop_bits_button_group"/>
 | 
			
		||||
  <buttongroup name="TX_audio_source_button_group"/>
 | 
			
		||||
  <buttongroup name="PTT_method_button_group"/>
 | 
			
		||||
  <buttongroup name="TX_mode_button_group"/>
 | 
			
		||||
  <buttongroup name="CAT_handshake_button_group"/>
 | 
			
		||||
  <buttongroup name="TX_audio_source_button_group"/>
 | 
			
		||||
  <buttongroup name="CAT_stop_bits_button_group"/>
 | 
			
		||||
  <buttongroup name="CAT_data_bits_button_group"/>
 | 
			
		||||
  <buttongroup name="PTT_method_button_group"/>
 | 
			
		||||
 </buttongroups>
 | 
			
		||||
</ui>
 | 
			
		||||
 | 
			
		||||
@ -4,15 +4,24 @@
 | 
			
		||||
 | 
			
		||||
#include "CandidateKeyFilter.hpp"
 | 
			
		||||
 | 
			
		||||
ForeignKeyDelegate::ForeignKeyDelegate (QAbstractItemModel const * referencing_model
 | 
			
		||||
                                        , QAbstractItemModel * referenced_model
 | 
			
		||||
                                        , int referencing_key_column
 | 
			
		||||
ForeignKeyDelegate::ForeignKeyDelegate (QAbstractItemModel * referenced_model
 | 
			
		||||
                                        , int referenced_key_column
 | 
			
		||||
                                        , QObject * parent
 | 
			
		||||
                                        , int referencing_key_role
 | 
			
		||||
                                        , int referenced_key_role)
 | 
			
		||||
  : QStyledItemDelegate {parent}
 | 
			
		||||
  , candidate_key_filter_ {new CandidateKeyFilter {referencing_model, referenced_model, referencing_key_column, referenced_key_column, referencing_key_role, referenced_key_role}}
 | 
			
		||||
  , candidate_key_filter_ {new CandidateKeyFilter {referenced_model, referenced_key_column, nullptr, referenced_key_role}}
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ForeignKeyDelegate::ForeignKeyDelegate (QAbstractItemModel * referenced_model
 | 
			
		||||
                                        , QAbstractItemModel const * referencing_model
 | 
			
		||||
                                        , int referenced_key_column
 | 
			
		||||
                                        , int referencing_key_column
 | 
			
		||||
                                        , QObject * parent
 | 
			
		||||
                                        , int referenced_key_role
 | 
			
		||||
                                        , int referencing_key_role)
 | 
			
		||||
  : QStyledItemDelegate {parent}
 | 
			
		||||
  , candidate_key_filter_ {new CandidateKeyFilter {referenced_model, referencing_model, referenced_key_column, referencing_key_column, nullptr, referenced_key_role, referencing_key_role}}
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -17,13 +17,20 @@ class ForeignKeyDelegate final
 | 
			
		||||
  : public QStyledItemDelegate
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  explicit ForeignKeyDelegate (QAbstractItemModel const * referencing_model
 | 
			
		||||
                               , QAbstractItemModel * referenced_model
 | 
			
		||||
                               , int referencing_key_column = 0
 | 
			
		||||
                               , int referenced_key_column = 0
 | 
			
		||||
  // many to many relationship
 | 
			
		||||
  explicit ForeignKeyDelegate (QAbstractItemModel * referenced_model
 | 
			
		||||
                               , int referenced_key_column
 | 
			
		||||
                               , QObject * parent = nullptr
 | 
			
		||||
                               , int referencing_key_role = Qt::EditRole
 | 
			
		||||
                               , int referenced_key_role = Qt::EditRole);
 | 
			
		||||
 | 
			
		||||
  // one to many (referenced to referencing) relationship
 | 
			
		||||
  explicit ForeignKeyDelegate (QAbstractItemModel * referenced_model
 | 
			
		||||
                               , QAbstractItemModel const * referencing_model
 | 
			
		||||
                               , int referenced_key_column
 | 
			
		||||
                               , int referencing_key_column
 | 
			
		||||
                               , QObject * parent = nullptr
 | 
			
		||||
                               , int referenced_key_role = Qt::EditRole
 | 
			
		||||
                               , int referencing_key_role = Qt::EditRole);
 | 
			
		||||
  ~ForeignKeyDelegate ();
 | 
			
		||||
 | 
			
		||||
  QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
 | 
			
		||||
 | 
			
		||||
@ -1,15 +1,6 @@
 | 
			
		||||
#include "FrequencyItemDelegate.hpp"
 | 
			
		||||
 | 
			
		||||
#include "Radio.hpp"
 | 
			
		||||
#include "FrequencyLineEdit.hpp"
 | 
			
		||||
#include "Bands.hpp"
 | 
			
		||||
 | 
			
		||||
QString FrequencyItemDelegate::displayText (QVariant const& value, QLocale const& locale) const
 | 
			
		||||
{
 | 
			
		||||
  auto frequency = value.value<Radio::Frequency> ();
 | 
			
		||||
  auto band_name = bands_->data (bands_->find (frequency));
 | 
			
		||||
  return Radio::pretty_frequency_MHz_string (frequency, locale) + " MHz (" + band_name.toString () + ')';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QWidget * FrequencyItemDelegate::createEditor (QWidget * parent
 | 
			
		||||
					       , QStyleOptionViewItem const& /* option */
 | 
			
		||||
@ -21,11 +12,6 @@ QWidget * FrequencyItemDelegate::createEditor (QWidget * parent
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
QString FrequencyDeltaItemDelegate::displayText (QVariant const& value, QLocale const& locale) const
 | 
			
		||||
{
 | 
			
		||||
  return Radio::pretty_frequency_MHz_string (value.value<Radio::FrequencyDelta> (), locale) + " MHz";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QWidget * FrequencyDeltaItemDelegate::createEditor (QWidget * parent
 | 
			
		||||
					       , QStyleOptionViewItem const& /* option */
 | 
			
		||||
					       , QModelIndex const& /* index */) const
 | 
			
		||||
 | 
			
		||||
@ -3,8 +3,6 @@
 | 
			
		||||
 | 
			
		||||
#include <QStyledItemDelegate>
 | 
			
		||||
 | 
			
		||||
class Bands;
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Class FrequencyItemDelegate
 | 
			
		||||
//
 | 
			
		||||
@ -16,17 +14,12 @@ class FrequencyItemDelegate final
 | 
			
		||||
  : public QStyledItemDelegate
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  explicit FrequencyItemDelegate (Bands const * bands, QObject * parent = nullptr)
 | 
			
		||||
  explicit FrequencyItemDelegate (QObject * parent = nullptr)
 | 
			
		||||
    : QStyledItemDelegate {parent}
 | 
			
		||||
    , bands_ {bands}
 | 
			
		||||
  {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QString displayText (QVariant const& value, QLocale const&) const override;
 | 
			
		||||
  QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  Bands const * bands_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -46,7 +39,6 @@ public:
 | 
			
		||||
  {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QString displayText (QVariant const& value, QLocale const&) const override;
 | 
			
		||||
  QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -11,25 +11,120 @@
 | 
			
		||||
#include <QMimeData>
 | 
			
		||||
#include <QDataStream>
 | 
			
		||||
#include <QByteArray>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
 | 
			
		||||
#include "Bands.hpp"
 | 
			
		||||
#include "pimpl_impl.hpp"
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
  FrequencyList::FrequencyItems const default_frequency_list =
 | 
			
		||||
    {
 | 
			
		||||
      {136000, Modes::WSPR},
 | 
			
		||||
      {136130, Modes::JT65},
 | 
			
		||||
      {474200, Modes::JT65},
 | 
			
		||||
      {474200, Modes::JT9},
 | 
			
		||||
      {474200, Modes::WSPR},
 | 
			
		||||
      {1836600, Modes::WSPR},
 | 
			
		||||
      {1838000, Modes::JT65},
 | 
			
		||||
      {1840000, Modes::JT9},
 | 
			
		||||
      {3576000, Modes::JT65},
 | 
			
		||||
      {3578000, Modes::JT9},
 | 
			
		||||
      {3559260, Modes::WSPR},
 | 
			
		||||
      {5357000, Modes::JT65},
 | 
			
		||||
      {5287200, Modes::WSPR},
 | 
			
		||||
      {7038600, Modes::WSPR},
 | 
			
		||||
      {7076000, Modes::JT65},
 | 
			
		||||
      {7078000, Modes::JT9},
 | 
			
		||||
      {10138000, Modes::JT65},
 | 
			
		||||
      {10138700, Modes::WSPR},
 | 
			
		||||
      {10140000, Modes::JT9},
 | 
			
		||||
      {14095600, Modes::WSPR},
 | 
			
		||||
      {14076000, Modes::JT65},
 | 
			
		||||
      {14078000, Modes::JT9},
 | 
			
		||||
      {18102000, Modes::JT65},
 | 
			
		||||
      {18104000, Modes::JT9},
 | 
			
		||||
      {18104460, Modes::WSPR},
 | 
			
		||||
      {21076000, Modes::JT65},
 | 
			
		||||
      {21078000, Modes::JT9},
 | 
			
		||||
      {21094600, Modes::WSPR},
 | 
			
		||||
      {24917000, Modes::JT65},
 | 
			
		||||
      {24919000, Modes::JT9},
 | 
			
		||||
      {24924600, Modes::WSPR},
 | 
			
		||||
      {28076000, Modes::JT65},
 | 
			
		||||
      {28078000, Modes::JT9},
 | 
			
		||||
      {28124600, Modes::WSPR},
 | 
			
		||||
      {50276000, Modes::JT65},
 | 
			
		||||
      {50293000, Modes::WSPR},
 | 
			
		||||
      {70091000, Modes::JT65},
 | 
			
		||||
      {70091000, Modes::WSPR},
 | 
			
		||||
      {144000000, Modes::JT4},
 | 
			
		||||
      {144489000, Modes::JT65},
 | 
			
		||||
      {144489000, Modes::WSPR},
 | 
			
		||||
      {222000000, Modes::JT4},
 | 
			
		||||
      {222000000, Modes::JT65},
 | 
			
		||||
      {432000000, Modes::JT4},
 | 
			
		||||
      {432000000, Modes::JT65},
 | 
			
		||||
      {432300000, Modes::WSPR},
 | 
			
		||||
      {902000000, Modes::JT4},
 | 
			
		||||
      {902000000, Modes::JT65},
 | 
			
		||||
      {1296000000, Modes::JT4},
 | 
			
		||||
      {1296000000, Modes::JT65},
 | 
			
		||||
      {1296500000, Modes::WSPR},
 | 
			
		||||
      {2301000000, Modes::JT4},
 | 
			
		||||
      {2301000000, Modes::JT65},
 | 
			
		||||
      {2304000000, Modes::JT4},
 | 
			
		||||
      {2304000000, Modes::JT65},
 | 
			
		||||
      {2320000000, Modes::JT4},
 | 
			
		||||
      {2320000000, Modes::JT65},
 | 
			
		||||
      {3400000000, Modes::JT4},
 | 
			
		||||
      {3400000000, Modes::JT65},
 | 
			
		||||
      {3456000000, Modes::JT4},
 | 
			
		||||
      {3456000000, Modes::JT65},
 | 
			
		||||
      {5760000000, Modes::JT4},
 | 
			
		||||
      {5760000000, Modes::JT65},
 | 
			
		||||
      {10368000000, Modes::JT4},
 | 
			
		||||
      {10368000000, Modes::JT65},
 | 
			
		||||
      {24048000000, Modes::JT4},
 | 
			
		||||
      {24048000000, Modes::JT65},
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if !defined (QT_NO_DEBUG_STREAM)
 | 
			
		||||
QDebug operator << (QDebug debug, FrequencyList::Item const& item)
 | 
			
		||||
{
 | 
			
		||||
  debug.nospace () << "FrequencyItem("
 | 
			
		||||
                   << item.frequency_ << ", "
 | 
			
		||||
                   << item.mode_ << ')';
 | 
			
		||||
  return debug.space ();
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
QDataStream& operator << (QDataStream& os, FrequencyList::Item const& item)
 | 
			
		||||
{
 | 
			
		||||
  return os << item.frequency_
 | 
			
		||||
            << item.mode_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QDataStream& operator >> (QDataStream& is, FrequencyList::Item& item)
 | 
			
		||||
{
 | 
			
		||||
  return is >> item.frequency_
 | 
			
		||||
            >> item.mode_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class FrequencyList::impl final
 | 
			
		||||
  : public QAbstractTableModel
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  impl (Frequencies frequencies, QObject * parent)
 | 
			
		||||
  impl (Bands const * bands, QObject * parent)
 | 
			
		||||
    : QAbstractTableModel {parent}
 | 
			
		||||
    , frequencies_ {frequencies}
 | 
			
		||||
    , bands_ {bands}
 | 
			
		||||
    , mode_filter_ {Modes::NULL_MODE}
 | 
			
		||||
  {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Frequencies const& frequencies () const {return frequencies_;}
 | 
			
		||||
  void assign (Frequencies);
 | 
			
		||||
  QModelIndex add (Frequency);
 | 
			
		||||
  FrequencyItems frequency_list (FrequencyItems);
 | 
			
		||||
  QModelIndex add (Item);
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  // Implement the QAbstractTableModel interface
 | 
			
		||||
  int rowCount (QModelIndex const& parent = QModelIndex {}) const override;
 | 
			
		||||
  int columnCount (QModelIndex const& parent = QModelIndex {}) const override;
 | 
			
		||||
@ -42,21 +137,17 @@ protected:
 | 
			
		||||
  QStringList mimeTypes () const override;
 | 
			
		||||
  QMimeData * mimeData (QModelIndexList const&) const override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  static int constexpr num_cols {2};
 | 
			
		||||
  static int constexpr num_cols {3};
 | 
			
		||||
  static auto constexpr mime_type ="application/wsjt.Frequencies";
 | 
			
		||||
 | 
			
		||||
  Frequencies frequencies_;
 | 
			
		||||
  Bands const * bands_;
 | 
			
		||||
  FrequencyItems frequency_list_;
 | 
			
		||||
  Mode mode_filter_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
FrequencyList::FrequencyList (QObject * parent)
 | 
			
		||||
  : FrequencyList {{}, parent}
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FrequencyList::FrequencyList (Frequencies frequencies, QObject * parent)
 | 
			
		||||
FrequencyList::FrequencyList (Bands const * bands, QObject * parent)
 | 
			
		||||
  : QSortFilterProxyModel {parent}
 | 
			
		||||
  , m_ {frequencies, parent}
 | 
			
		||||
  , m_ {bands, parent}
 | 
			
		||||
{
 | 
			
		||||
  setSourceModel (&*m_);
 | 
			
		||||
  setSortRole (SortRole);
 | 
			
		||||
@ -66,25 +157,52 @@ FrequencyList::~FrequencyList ()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FrequencyList& FrequencyList::operator = (Frequencies frequencies)
 | 
			
		||||
auto FrequencyList::frequency_list (FrequencyItems frequency_list) -> FrequencyItems
 | 
			
		||||
{
 | 
			
		||||
  m_->assign (frequencies);
 | 
			
		||||
  return *this;
 | 
			
		||||
  return m_->frequency_list (frequency_list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto FrequencyList::frequencies () const -> Frequencies
 | 
			
		||||
auto FrequencyList::frequency_list () const -> FrequencyItems const&
 | 
			
		||||
{
 | 
			
		||||
  return m_->frequencies ();
 | 
			
		||||
  return m_->frequency_list_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QModelIndex FrequencyList::add (Frequency f)
 | 
			
		||||
QModelIndex FrequencyList::best_working_frequency (Frequency f, Mode mode) const
 | 
			
		||||
{
 | 
			
		||||
  auto const& target_band = m_->bands_->find (f);
 | 
			
		||||
  if (target_band != m_->bands_->out_of_band ())
 | 
			
		||||
    {
 | 
			
		||||
      // find a frequency in the same band that is allowed for the
 | 
			
		||||
      // target mode
 | 
			
		||||
      for (int row = 0; row < rowCount (); ++row)
 | 
			
		||||
        {
 | 
			
		||||
          auto const& source_row = mapToSource (index (row, 0)).row ();
 | 
			
		||||
          auto const& band = m_->bands_->find (m_->frequency_list_[source_row].frequency_);
 | 
			
		||||
          if (band->name_ == target_band->name_)
 | 
			
		||||
            {
 | 
			
		||||
              if (m_->frequency_list_[source_row].mode_ == mode)
 | 
			
		||||
                {
 | 
			
		||||
                  return index (row, 0);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  return QModelIndex {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FrequencyList::reset_to_defaults ()
 | 
			
		||||
{
 | 
			
		||||
  m_->frequency_list (default_frequency_list);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QModelIndex FrequencyList::add (Item f)
 | 
			
		||||
{
 | 
			
		||||
  return mapFromSource (m_->add (f));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FrequencyList::remove (Frequency f)
 | 
			
		||||
bool FrequencyList::remove (Item f)
 | 
			
		||||
{
 | 
			
		||||
  auto row = m_->frequencies ().indexOf (f);
 | 
			
		||||
  auto row = m_->frequency_list_.indexOf (f);
 | 
			
		||||
 | 
			
		||||
  if (0 > row)
 | 
			
		||||
    {
 | 
			
		||||
@ -123,38 +241,54 @@ bool FrequencyList::removeDisjointRows (QModelIndexList rows)
 | 
			
		||||
          result = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void FrequencyList::filter (Mode mode)
 | 
			
		||||
{
 | 
			
		||||
  m_->mode_filter_ = mode;
 | 
			
		||||
  invalidateFilter ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool FrequencyList::filterAcceptsRow (int source_row, QModelIndex const& /* parent */) const
 | 
			
		||||
{
 | 
			
		||||
  bool result {true};
 | 
			
		||||
  if (m_->mode_filter_ != Modes::NULL_MODE)
 | 
			
		||||
    {
 | 
			
		||||
      auto const& item = m_->frequency_list_[source_row];
 | 
			
		||||
      result = item.mode_ == Modes::NULL_MODE || m_->mode_filter_ == item.mode_;
 | 
			
		||||
    }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void FrequencyList::impl::assign (Frequencies frequencies)
 | 
			
		||||
auto FrequencyList::impl::frequency_list (FrequencyItems frequency_list) -> FrequencyItems
 | 
			
		||||
{
 | 
			
		||||
  beginResetModel ();
 | 
			
		||||
  std::swap (frequencies_, frequencies);
 | 
			
		||||
  std::swap (frequency_list_, frequency_list);
 | 
			
		||||
  endResetModel ();
 | 
			
		||||
  return frequency_list;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QModelIndex FrequencyList::impl::add (Frequency f)
 | 
			
		||||
QModelIndex FrequencyList::impl::add (Item f)
 | 
			
		||||
{
 | 
			
		||||
  // Any Frequency that isn't in the list may be added
 | 
			
		||||
  if (!frequencies_.contains (f))
 | 
			
		||||
  if (!frequency_list_.contains (f))
 | 
			
		||||
    {
 | 
			
		||||
      auto row = frequencies_.size ();
 | 
			
		||||
      auto row = frequency_list_.size ();
 | 
			
		||||
 | 
			
		||||
      beginInsertRows (QModelIndex {}, row, row);
 | 
			
		||||
      frequencies_.append (f);
 | 
			
		||||
      frequency_list_.append (f);
 | 
			
		||||
      endInsertRows ();
 | 
			
		||||
 | 
			
		||||
      return index (row, 0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return QModelIndex {};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FrequencyList::impl::rowCount (QModelIndex const& parent) const
 | 
			
		||||
{
 | 
			
		||||
  return parent.isValid () ? 0 : frequencies_.size ();
 | 
			
		||||
  return parent.isValid () ? 0 : frequency_list_.size ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int FrequencyList::impl::columnCount (QModelIndex const& parent) const
 | 
			
		||||
@ -165,26 +299,17 @@ int FrequencyList::impl::columnCount (QModelIndex const& parent) const
 | 
			
		||||
Qt::ItemFlags FrequencyList::impl::flags (QModelIndex const& index) const
 | 
			
		||||
{
 | 
			
		||||
  auto result = QAbstractTableModel::flags (index) | Qt::ItemIsDropEnabled;
 | 
			
		||||
 | 
			
		||||
  auto row = index.row ();
 | 
			
		||||
  auto column = index.column ();
 | 
			
		||||
 | 
			
		||||
  if (index.isValid ()
 | 
			
		||||
      && row < frequencies_.size ()
 | 
			
		||||
      && row < frequency_list_.size ()
 | 
			
		||||
      && column < num_cols)
 | 
			
		||||
    {
 | 
			
		||||
      switch (column)
 | 
			
		||||
      if (frequency_mhz_column != column)
 | 
			
		||||
        {
 | 
			
		||||
        case 0:
 | 
			
		||||
          result |= Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case 1:
 | 
			
		||||
          result |= Qt::ItemIsDragEnabled;
 | 
			
		||||
          break;
 | 
			
		||||
          result |= Qt::ItemIsEditable | Qt::ItemIsDragEnabled;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -192,25 +317,51 @@ QVariant FrequencyList::impl::data (QModelIndex const& index, int role) const
 | 
			
		||||
{
 | 
			
		||||
  QVariant item;
 | 
			
		||||
 | 
			
		||||
  auto row = index.row ();
 | 
			
		||||
  auto column = index.column ();
 | 
			
		||||
  auto const& row = index.row ();
 | 
			
		||||
  auto const& column = index.column ();
 | 
			
		||||
 | 
			
		||||
  if (index.isValid ()
 | 
			
		||||
      && row < frequencies_.size ()
 | 
			
		||||
      && row < frequency_list_.size ()
 | 
			
		||||
      && column < num_cols)
 | 
			
		||||
    {
 | 
			
		||||
      auto frequency = frequencies_.at (row);
 | 
			
		||||
 | 
			
		||||
      auto const& frequency_item = frequency_list_.at (row);
 | 
			
		||||
      switch (column)
 | 
			
		||||
        {
 | 
			
		||||
        case 0:
 | 
			
		||||
        case mode_column:
 | 
			
		||||
          switch (role)
 | 
			
		||||
            {
 | 
			
		||||
            case SortRole:
 | 
			
		||||
            case Qt::DisplayRole:
 | 
			
		||||
            case Qt::EditRole:
 | 
			
		||||
            case Qt::AccessibleTextRole:
 | 
			
		||||
              item = frequency;
 | 
			
		||||
              item = Modes::name (frequency_item.mode_);
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case Qt::ToolTipRole:
 | 
			
		||||
            case Qt::AccessibleDescriptionRole:
 | 
			
		||||
              item = tr ("Mode");
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case Qt::TextAlignmentRole:
 | 
			
		||||
              item = Qt::AlignHCenter + Qt::AlignVCenter;
 | 
			
		||||
              break;
 | 
			
		||||
            }
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case frequency_column:
 | 
			
		||||
          switch (role)
 | 
			
		||||
            {
 | 
			
		||||
            case SortRole:
 | 
			
		||||
            case Qt::EditRole:
 | 
			
		||||
            case Qt::AccessibleTextRole:
 | 
			
		||||
              item = frequency_item.frequency_;
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case Qt::DisplayRole:
 | 
			
		||||
              {
 | 
			
		||||
                auto const& band = bands_->find (frequency_item.frequency_);
 | 
			
		||||
                item = Radio::pretty_frequency_MHz_string (frequency_item.frequency_) + " MHz (" + band->name_ + ')';
 | 
			
		||||
              }
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case Qt::ToolTipRole:
 | 
			
		||||
@ -224,22 +375,24 @@ QVariant FrequencyList::impl::data (QModelIndex const& index, int role) const
 | 
			
		||||
            }
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case 1:
 | 
			
		||||
        case frequency_mhz_column:
 | 
			
		||||
          switch (role)
 | 
			
		||||
            {
 | 
			
		||||
            case Qt::DisplayRole:
 | 
			
		||||
            case Qt::EditRole:
 | 
			
		||||
            case Qt::AccessibleTextRole:
 | 
			
		||||
              item = static_cast<double> (frequency / 1.e6);
 | 
			
		||||
              item = frequency_item.frequency_ / 1.e6;
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case SortRole:	// use the underlying Frequency value
 | 
			
		||||
              item = frequency;
 | 
			
		||||
            case Qt::DisplayRole:
 | 
			
		||||
              {
 | 
			
		||||
                auto const& band = bands_->find (frequency_item.frequency_);
 | 
			
		||||
                item = Radio::pretty_frequency_MHz_string (frequency_item.frequency_) + " MHz (" + band->name_ + ')';
 | 
			
		||||
              }
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case Qt::ToolTipRole:
 | 
			
		||||
            case Qt::AccessibleDescriptionRole:
 | 
			
		||||
              item = tr ("Frequency MHz");
 | 
			
		||||
              item = tr ("Frequency (MHz)");
 | 
			
		||||
              break;
 | 
			
		||||
 | 
			
		||||
            case Qt::TextAlignmentRole:
 | 
			
		||||
@ -249,7 +402,6 @@ QVariant FrequencyList::impl::data (QModelIndex const& index, int role) const
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return item;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -257,21 +409,44 @@ bool FrequencyList::impl::setData (QModelIndex const& model_index, QVariant cons
 | 
			
		||||
{
 | 
			
		||||
  bool changed {false};
 | 
			
		||||
 | 
			
		||||
  auto row = model_index.row ();
 | 
			
		||||
  auto const& row = model_index.row ();
 | 
			
		||||
  if (model_index.isValid ()
 | 
			
		||||
      && Qt::EditRole == role
 | 
			
		||||
      && row < frequencies_.size ()
 | 
			
		||||
      && 0 == model_index.column ()
 | 
			
		||||
      && value.canConvert<Frequency> ())
 | 
			
		||||
      && row < frequency_list_.size ())
 | 
			
		||||
    {
 | 
			
		||||
      auto frequency = value.value<Frequency> ();
 | 
			
		||||
      auto original_frequency = frequencies_.at (row);
 | 
			
		||||
      if (frequency != original_frequency)
 | 
			
		||||
      QVector<int> roles;
 | 
			
		||||
      roles << role;
 | 
			
		||||
 | 
			
		||||
      auto& item = frequency_list_[row];
 | 
			
		||||
      switch (model_index.column ())
 | 
			
		||||
        {
 | 
			
		||||
          frequencies_.replace (row, frequency);
 | 
			
		||||
          Q_EMIT dataChanged (model_index, index (model_index.row (), 1), QVector<int> {} << role);
 | 
			
		||||
        case mode_column:
 | 
			
		||||
          if (value.canConvert<Mode> ())
 | 
			
		||||
            {
 | 
			
		||||
              auto mode = Modes::value (value.toString ());
 | 
			
		||||
              if (mode != item.mode_)
 | 
			
		||||
                {
 | 
			
		||||
                  item.mode_ = mode;
 | 
			
		||||
                  Q_EMIT dataChanged (model_index, model_index, roles);
 | 
			
		||||
                  changed = true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case frequency_column:
 | 
			
		||||
          if (value.canConvert<Frequency> ())
 | 
			
		||||
            {
 | 
			
		||||
              auto frequency = value.value<Frequency> ();
 | 
			
		||||
              if (frequency != item.frequency_)
 | 
			
		||||
                {
 | 
			
		||||
                  item.frequency_ = frequency;
 | 
			
		||||
                  // mark derived column (1) changed as well
 | 
			
		||||
                  Q_EMIT dataChanged (index (model_index.row (), 1), model_index, roles);
 | 
			
		||||
                  changed = true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
      changed = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return changed;
 | 
			
		||||
@ -280,22 +455,21 @@ bool FrequencyList::impl::setData (QModelIndex const& model_index, QVariant cons
 | 
			
		||||
QVariant FrequencyList::impl::headerData (int section, Qt::Orientation orientation, int role) const
 | 
			
		||||
{
 | 
			
		||||
  QVariant header;
 | 
			
		||||
 | 
			
		||||
  if (Qt::DisplayRole == role
 | 
			
		||||
      && Qt::Horizontal == orientation
 | 
			
		||||
      && section < num_cols)
 | 
			
		||||
    {
 | 
			
		||||
      switch (section)
 | 
			
		||||
        {
 | 
			
		||||
        case 0: header = tr ("Frequency"); break;
 | 
			
		||||
        case 1: header = tr ("Frequency (MHz)"); break;
 | 
			
		||||
        case mode_column: header = tr ("Mode"); break;
 | 
			
		||||
        case frequency_column: header = tr ("Frequency"); break;
 | 
			
		||||
        case frequency_mhz_column: header = tr ("Frequency (MHz)"); break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      header = QAbstractTableModel::headerData (section, orientation, role);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return header;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -306,12 +480,11 @@ bool FrequencyList::impl::removeRows (int row, int count, QModelIndex const& par
 | 
			
		||||
      beginRemoveRows (parent, row, row + count - 1);
 | 
			
		||||
      for (auto r = 0; r < count; ++r)
 | 
			
		||||
        {
 | 
			
		||||
          frequencies_.removeAt (row);
 | 
			
		||||
          frequency_list_.removeAt (row);
 | 
			
		||||
        }
 | 
			
		||||
      endRemoveRows ();
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -322,12 +495,11 @@ bool FrequencyList::impl::insertRows (int row, int count, QModelIndex const& par
 | 
			
		||||
      beginInsertRows (parent, row, row + count - 1);
 | 
			
		||||
      for (auto r = 0; r < count; ++r)
 | 
			
		||||
        {
 | 
			
		||||
          frequencies_.insert (row, Frequency {});
 | 
			
		||||
          frequency_list_.insert (row, Item {0, Mode::NULL_MODE});
 | 
			
		||||
        }
 | 
			
		||||
      endInsertRows ();
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -346,7 +518,7 @@ QMimeData * FrequencyList::impl::mimeData (QModelIndexList const& items) const
 | 
			
		||||
 | 
			
		||||
  Q_FOREACH (auto const& item, items)
 | 
			
		||||
    {
 | 
			
		||||
      if (item.isValid ())
 | 
			
		||||
      if (item.isValid () && frequency_column == item.column ())
 | 
			
		||||
        {
 | 
			
		||||
          stream << QString {data (item, Qt::DisplayRole).toString ()};
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -3,9 +3,13 @@
 | 
			
		||||
 | 
			
		||||
#include "pimpl_h.hpp"
 | 
			
		||||
 | 
			
		||||
#include <QList>
 | 
			
		||||
#include <QSortFilterProxyModel>
 | 
			
		||||
 | 
			
		||||
#include "Radio.hpp"
 | 
			
		||||
#include "Modes.hpp"
 | 
			
		||||
 | 
			
		||||
class Bands;
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Class FrequencyList
 | 
			
		||||
@ -31,23 +35,45 @@
 | 
			
		||||
class FrequencyList final
 | 
			
		||||
  : public QSortFilterProxyModel
 | 
			
		||||
{
 | 
			
		||||
  Q_OBJECT;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  using Frequency = Radio::Frequency;
 | 
			
		||||
  using Frequencies = Radio::Frequencies;
 | 
			
		||||
  using Mode = Modes::Mode;
 | 
			
		||||
 | 
			
		||||
  explicit FrequencyList (QObject * parent = nullptr);
 | 
			
		||||
  explicit FrequencyList (Frequencies, QObject * parent = nullptr);
 | 
			
		||||
  struct Item
 | 
			
		||||
  {
 | 
			
		||||
    Frequency frequency_;
 | 
			
		||||
    Mode mode_;
 | 
			
		||||
  };
 | 
			
		||||
  using FrequencyItems = QList<Item>;
 | 
			
		||||
 | 
			
		||||
  enum Column {mode_column, frequency_column, frequency_mhz_column};
 | 
			
		||||
 | 
			
		||||
  explicit FrequencyList (Bands const *, QObject * parent = nullptr);
 | 
			
		||||
  ~FrequencyList ();
 | 
			
		||||
 | 
			
		||||
  // Load and store contents
 | 
			
		||||
  FrequencyList& operator = (Frequencies);
 | 
			
		||||
  Frequencies frequencies () const;
 | 
			
		||||
  FrequencyItems frequency_list (FrequencyItems);
 | 
			
		||||
  FrequencyItems const& frequency_list () const;
 | 
			
		||||
 | 
			
		||||
  // Find nearest best working frequency given a frequency and mode
 | 
			
		||||
  QModelIndex best_working_frequency (Frequency, Mode) const;
 | 
			
		||||
 | 
			
		||||
  // Set filter
 | 
			
		||||
  void filter (Mode);
 | 
			
		||||
 | 
			
		||||
  // Reset
 | 
			
		||||
  Q_SLOT void reset_to_defaults ();
 | 
			
		||||
 | 
			
		||||
  // Model API
 | 
			
		||||
  QModelIndex add (Frequency);
 | 
			
		||||
  bool remove (Frequency);
 | 
			
		||||
  QModelIndex add (Item);
 | 
			
		||||
  bool remove (Item);
 | 
			
		||||
  bool removeDisjointRows (QModelIndexList);
 | 
			
		||||
 | 
			
		||||
  // Proxy API
 | 
			
		||||
  bool filterAcceptsRow (int source_row, QModelIndex const& parent) const override;
 | 
			
		||||
 | 
			
		||||
  // Custom roles.
 | 
			
		||||
  static int constexpr SortRole = Qt::UserRole;
 | 
			
		||||
 | 
			
		||||
@ -56,4 +82,22 @@ private:
 | 
			
		||||
  pimpl<impl> m_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline
 | 
			
		||||
bool operator == (FrequencyList::Item const& lhs, FrequencyList::Item const& rhs)
 | 
			
		||||
{
 | 
			
		||||
  return
 | 
			
		||||
    lhs.frequency_ == rhs.frequency_
 | 
			
		||||
    && lhs.mode_ == rhs.mode_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QDataStream& operator << (QDataStream&, FrequencyList::Item const&);
 | 
			
		||||
QDataStream& operator >> (QDataStream&, FrequencyList::Item&);
 | 
			
		||||
 | 
			
		||||
#if !defined (QT_NO_DEBUG_STREAM)
 | 
			
		||||
QDebug operator << (QDebug, FrequencyList::Item const&);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
Q_DECLARE_METATYPE (FrequencyList::Item);
 | 
			
		||||
Q_DECLARE_METATYPE (FrequencyList::FrequencyItems);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -15,16 +15,16 @@ LiveFrequencyValidator::LiveFrequencyValidator (QComboBox * combo_box
 | 
			
		||||
                                                , FrequencyList const * frequencies
 | 
			
		||||
                                                , QWidget * parent)
 | 
			
		||||
  : QRegExpValidator {
 | 
			
		||||
  QRegExp {				// frequency in MHz or band
 | 
			
		||||
    bands->data (QModelIndex {}).toString () // out of band string
 | 
			
		||||
      + QString {R"(|((\d{0,6}(\)"}		 // up to 6 digits
 | 
			
		||||
    + QLocale {}.decimalPoint () // (followed by decimal separator
 | 
			
		||||
                   + R"(\d{0,2})?)([Mm]{1,2}|([Cc][Mm])))|(\d{0,4}(\)" // followed by up to 2 digits and either 'm' or 'cm' or 'mm' (case insensitive))
 | 
			
		||||
                   + QLocale {}.decimalPoint () // or a decimal separator
 | 
			
		||||
                                  + R"(\d{0,6})?))"	       //  followed by up to 6 digits
 | 
			
		||||
                                  }
 | 
			
		||||
  , parent
 | 
			
		||||
      QRegExp {       // frequency in MHz or band
 | 
			
		||||
        bands->data (QModelIndex {}).toString () // out of band string
 | 
			
		||||
          + QString {R"(|((\d{0,6}(\)"}    // or up to 6 digits
 | 
			
		||||
          + QLocale {}.decimalPoint () // (followed by decimal separator
 | 
			
		||||
          + R"(\d{0,2})?)([Mm]{1,2}|([Cc][Mm])))|(\d{0,4}(\)" // followed by up to 2 digits and either 'm' or 'cm' or 'mm' (case insensitive))
 | 
			
		||||
          + QLocale {}.decimalPoint () // or a decimal separator
 | 
			
		||||
          + R"(\d{0,6})?))"        //  followed by up to 6 digits
 | 
			
		||||
      }
 | 
			
		||||
      , parent
 | 
			
		||||
    }
 | 
			
		||||
  , bands_ {bands}
 | 
			
		||||
  , frequencies_ {frequencies}
 | 
			
		||||
  , combo_box_ {combo_box}
 | 
			
		||||
@ -34,7 +34,6 @@ LiveFrequencyValidator::LiveFrequencyValidator (QComboBox * combo_box
 | 
			
		||||
auto LiveFrequencyValidator::validate (QString& input, int& pos) const -> State
 | 
			
		||||
{
 | 
			
		||||
  auto state = QRegExpValidator::validate (input, pos);
 | 
			
		||||
 | 
			
		||||
  // by never being Acceptable we force fixup calls on ENTER or
 | 
			
		||||
  // losing focus
 | 
			
		||||
  return Acceptable == state ? Intermediate : state;
 | 
			
		||||
@ -43,50 +42,46 @@ auto LiveFrequencyValidator::validate (QString& input, int& pos) const -> State
 | 
			
		||||
void LiveFrequencyValidator::fixup (QString& input) const
 | 
			
		||||
{
 | 
			
		||||
  QRegExpValidator::fixup (input);
 | 
			
		||||
 | 
			
		||||
  auto out_of_band = bands_->data (QModelIndex {}).toString ();
 | 
			
		||||
 | 
			
		||||
  if (!out_of_band.startsWith (input))
 | 
			
		||||
  auto const& out_of_band = bands_->out_of_band ();
 | 
			
		||||
  if (!QString {out_of_band->name_}.startsWith (input))
 | 
			
		||||
    {
 | 
			
		||||
      if (input.contains ('m', Qt::CaseInsensitive))
 | 
			
		||||
	{
 | 
			
		||||
	  input = input.toLower ();
 | 
			
		||||
        {
 | 
			
		||||
          input = input.toLower ();
 | 
			
		||||
 | 
			
		||||
	  QVector<QVariant> frequencies;
 | 
			
		||||
	  for (int r = 0; r < frequencies_->rowCount (); ++r)
 | 
			
		||||
	    {
 | 
			
		||||
	      auto frequency = frequencies_->index (r, 0).data ();
 | 
			
		||||
	      auto band_index = bands_->find (frequency);
 | 
			
		||||
	      if (band_index.data ().toString () == input)
 | 
			
		||||
		{
 | 
			
		||||
		  frequencies << frequency;
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	  if (!frequencies.isEmpty ())
 | 
			
		||||
	    {
 | 
			
		||||
	      Q_EMIT valid (frequencies.first ().value<Frequency> ());
 | 
			
		||||
	    }
 | 
			
		||||
	  else
 | 
			
		||||
	    {
 | 
			
		||||
	      input = QString {};
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
          QVector<QVariant> frequencies;
 | 
			
		||||
          Q_FOREACH (auto const& item, frequencies_->frequency_list ())
 | 
			
		||||
            {
 | 
			
		||||
              if (bands_->find (item.frequency_)->name_ == input)
 | 
			
		||||
                {
 | 
			
		||||
                  frequencies << item.frequency_;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
          if (!frequencies.isEmpty ())
 | 
			
		||||
            {
 | 
			
		||||
              Q_EMIT valid (frequencies.first ().value<Frequency> ());
 | 
			
		||||
            }
 | 
			
		||||
          else
 | 
			
		||||
            {
 | 
			
		||||
              input = QString {};
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
	{
 | 
			
		||||
	  // frequency input
 | 
			
		||||
	  auto f = Radio::frequency (input, 6);
 | 
			
		||||
	  input = bands_->data (bands_->find (f)).toString ();
 | 
			
		||||
	  Q_EMIT valid (f);
 | 
			
		||||
	}
 | 
			
		||||
        {
 | 
			
		||||
          // frequency input
 | 
			
		||||
          auto f = Radio::frequency (input, 6);
 | 
			
		||||
          input = bands_->find (f)->name_;
 | 
			
		||||
          Q_EMIT valid (f);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      if (out_of_band == input)
 | 
			
		||||
	{
 | 
			
		||||
	  combo_box_->lineEdit ()->setStyleSheet ("QLineEdit {color: yellow; background-color : red;}");
 | 
			
		||||
	}
 | 
			
		||||
      if (bands_->out_of_band ()->name_ == input)
 | 
			
		||||
        {
 | 
			
		||||
          combo_box_->lineEdit ()->setStyleSheet ("QLineEdit {color: yellow; background-color : red;}");
 | 
			
		||||
        }
 | 
			
		||||
      else
 | 
			
		||||
	{
 | 
			
		||||
	  combo_box_->lineEdit ()->setStyleSheet ({});
 | 
			
		||||
	}
 | 
			
		||||
        {
 | 
			
		||||
          combo_box_->lineEdit ()->setStyleSheet ({});
 | 
			
		||||
        }
 | 
			
		||||
      combo_box_->setCurrentText (input);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										72
									
								
								MetaDataRegistry.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								MetaDataRegistry.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,72 @@
 | 
			
		||||
#include "MetaDataRegistry.hpp"
 | 
			
		||||
 | 
			
		||||
#include <QMetaType>
 | 
			
		||||
#include <QItemEditorFactory>
 | 
			
		||||
#include <QStandardItemEditorCreator>
 | 
			
		||||
 | 
			
		||||
#include "Radio.hpp"
 | 
			
		||||
#include "FrequencyList.hpp"
 | 
			
		||||
#include "AudioDevice.hpp"
 | 
			
		||||
#include "Configuration.hpp"
 | 
			
		||||
#include "StationList.hpp"
 | 
			
		||||
#include "Transceiver.hpp"
 | 
			
		||||
#include "TransceiverFactory.hpp"
 | 
			
		||||
#include "WFPalette.hpp"
 | 
			
		||||
 | 
			
		||||
#include "FrequencyLineEdit.hpp"
 | 
			
		||||
 | 
			
		||||
void register_types ()
 | 
			
		||||
{
 | 
			
		||||
  // Default custom item view delegates
 | 
			
		||||
  auto factory = new QItemEditorFactory;
 | 
			
		||||
 | 
			
		||||
  // Radio namespace
 | 
			
		||||
  auto frequency_type_id = qRegisterMetaType<Radio::Frequency> ("Frequency");
 | 
			
		||||
  factory->registerEditor (frequency_type_id, new QStandardItemEditorCreator<FrequencyLineEdit> ());
 | 
			
		||||
  auto frequency_delta_type_id = qRegisterMetaType<Radio::FrequencyDelta> ("FrequencyDelta");
 | 
			
		||||
  factory->registerEditor (frequency_delta_type_id, new QStandardItemEditorCreator<FrequencyDeltaLineEdit> ());
 | 
			
		||||
 | 
			
		||||
  // Frequency list model
 | 
			
		||||
  qRegisterMetaType<FrequencyList::Item> ("Item");
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<FrequencyList::Item> ("Item");
 | 
			
		||||
  qRegisterMetaType<FrequencyList::FrequencyItems> ("FrequencyItems");
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<FrequencyList::FrequencyItems> ("FrequencyItems");
 | 
			
		||||
 | 
			
		||||
  // Audio device
 | 
			
		||||
  qRegisterMetaType<AudioDevice::Channel> ("AudioDevice::Channel");
 | 
			
		||||
 | 
			
		||||
  // Configuration
 | 
			
		||||
  qRegisterMetaType<Configuration::DataMode> ("Configuration::DataMode");
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<Configuration::DataMode> ("Configuration::DataMode");
 | 
			
		||||
  qRegisterMetaType<Configuration::Type2MsgGen> ("Configuration::Type2MsgGen");
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<Configuration::Type2MsgGen> ("Configuration::Type2MsgGen");
 | 
			
		||||
 | 
			
		||||
  // Station details
 | 
			
		||||
  qRegisterMetaType<StationList::Station> ("Station");
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<StationList::Station> ("Station");
 | 
			
		||||
  qRegisterMetaType<StationList::Stations> ("Stations");
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<StationList::Stations> ("Stations");
 | 
			
		||||
 | 
			
		||||
  // Transceiver
 | 
			
		||||
  qRegisterMetaType<Transceiver::TransceiverState> ("Transceiver::TransceiverState");
 | 
			
		||||
  qRegisterMetaType<Transceiver::MODE> ("Transceiver::MODE");
 | 
			
		||||
 | 
			
		||||
  // Transceiver factory
 | 
			
		||||
  qRegisterMetaType<TransceiverFactory::DataBits> ("TransceiverFactory::DataBits");
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<TransceiverFactory::DataBits> ("TransceiverFactory::DataBits");
 | 
			
		||||
  qRegisterMetaType<TransceiverFactory::StopBits> ("TransceiverFactory::StopBits");
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<TransceiverFactory::StopBits> ("TransceiverFactory::StopBits");
 | 
			
		||||
  qRegisterMetaType<TransceiverFactory::Handshake> ("TransceiverFactory::Handshake");
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<TransceiverFactory::Handshake> ("TransceiverFactory::Handshake");
 | 
			
		||||
  qRegisterMetaType<TransceiverFactory::PTTMethod> ("TransceiverFactory::PTTMethod");
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<TransceiverFactory::PTTMethod> ("TransceiverFactory::PTTMethod");
 | 
			
		||||
  qRegisterMetaType<TransceiverFactory::TXAudioSource> ("TransceiverFactory::TXAudioSource");
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<TransceiverFactory::TXAudioSource> ("TransceiverFactory::TXAudioSource");
 | 
			
		||||
  qRegisterMetaType<TransceiverFactory::SplitMode> ("TransceiverFactory::SplitMode");
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<TransceiverFactory::SplitMode> ("TransceiverFactory::SplitMode");
 | 
			
		||||
 | 
			
		||||
  // Waterfall palette
 | 
			
		||||
  qRegisterMetaTypeStreamOperators<WFPalette::Colours> ("Colours");
 | 
			
		||||
 | 
			
		||||
  QItemEditorFactory::setDefaultFactory (factory);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								MetaDataRegistry.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								MetaDataRegistry.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
#ifndef META_DATA_REGISTRY_HPP__
 | 
			
		||||
#define META_DATA_REGISTRY_HPP__
 | 
			
		||||
 | 
			
		||||
void register_types ();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										92
									
								
								Modes.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								Modes.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,92 @@
 | 
			
		||||
#include "Modes.hpp"
 | 
			
		||||
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QVariant>
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
  char const * const mode_names[] =
 | 
			
		||||
    {
 | 
			
		||||
      "",
 | 
			
		||||
      "JT65",
 | 
			
		||||
      "JT9",
 | 
			
		||||
      "JT9W-1",
 | 
			
		||||
      "JT4",
 | 
			
		||||
      "WSPR",
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Modes::Modes (QObject * parent)
 | 
			
		||||
  : QAbstractListModel {parent}
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char const * Modes::name (Mode m)
 | 
			
		||||
{
 | 
			
		||||
  return mode_names[static_cast<int> (m)];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto Modes::value (QString const& s) -> Mode
 | 
			
		||||
{
 | 
			
		||||
  auto end = mode_names + sizeof (mode_names) / sizeof (mode_names[0]);
 | 
			
		||||
  auto p = std::find_if (mode_names, end
 | 
			
		||||
                         , [&s] (char const * const name) {
 | 
			
		||||
                           return name == s;
 | 
			
		||||
                         });
 | 
			
		||||
  return p != end ? static_cast<Mode> (p - mode_names) : NULL_MODE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVariant Modes::data (QModelIndex const& index, int role) const
 | 
			
		||||
{
 | 
			
		||||
  QVariant item;
 | 
			
		||||
 | 
			
		||||
  if (index.isValid ())
 | 
			
		||||
    {
 | 
			
		||||
      auto const& row = index.row ();
 | 
			
		||||
      switch (role)
 | 
			
		||||
        {
 | 
			
		||||
        case Qt::ToolTipRole:
 | 
			
		||||
        case Qt::AccessibleDescriptionRole:
 | 
			
		||||
          item = tr ("Mode");
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case Qt::EditRole:
 | 
			
		||||
          item = static_cast<Mode> (row);
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case Qt::DisplayRole:
 | 
			
		||||
        case Qt::AccessibleTextRole:
 | 
			
		||||
          item = mode_names[row];
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case Qt::TextAlignmentRole:
 | 
			
		||||
          item = Qt::AlignHCenter + Qt::AlignVCenter;
 | 
			
		||||
          break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return item;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QVariant Modes::headerData (int section, Qt::Orientation orientation, int role) const
 | 
			
		||||
{
 | 
			
		||||
  QVariant result;
 | 
			
		||||
 | 
			
		||||
  if (Qt::DisplayRole == role && Qt::Horizontal == orientation)
 | 
			
		||||
    {
 | 
			
		||||
      result = tr ("Mode");
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      result = QAbstractListModel::headerData (section, orientation, role);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if !defined (QT_NO_DEBUG_STREAM)
 | 
			
		||||
ENUM_QDEBUG_OPS_IMPL (Modes, Mode);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
ENUM_QDATASTREAM_OPS_IMPL (Modes, Mode);
 | 
			
		||||
ENUM_CONVERSION_OPS_IMPL (Modes, Mode);
 | 
			
		||||
							
								
								
									
										49
									
								
								Modes.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								Modes.hpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,49 @@
 | 
			
		||||
#ifndef MODES_HPP__
 | 
			
		||||
#define MODES_HPP__
 | 
			
		||||
 | 
			
		||||
#include <QAbstractListModel>
 | 
			
		||||
 | 
			
		||||
#include "qt_helpers.hpp"
 | 
			
		||||
 | 
			
		||||
class Modes final
 | 
			
		||||
  : public QAbstractListModel
 | 
			
		||||
{
 | 
			
		||||
  Q_OBJECT;
 | 
			
		||||
  Q_ENUMS (Mode);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  enum Mode
 | 
			
		||||
  {
 | 
			
		||||
    NULL_MODE,
 | 
			
		||||
    JT65,
 | 
			
		||||
    JT9,
 | 
			
		||||
    JT9W_1,
 | 
			
		||||
    JT4,
 | 
			
		||||
    WSPR,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  explicit Modes (QObject * parent = nullptr);
 | 
			
		||||
 | 
			
		||||
  static char const * name (Mode);
 | 
			
		||||
  static Mode value (QString const&);
 | 
			
		||||
 | 
			
		||||
  // Implement the QAbstractListModel interface
 | 
			
		||||
  int rowCount (QModelIndex const& parent = QModelIndex {}) const override
 | 
			
		||||
  {
 | 
			
		||||
    return parent.isValid () ? 0 : 6; // the number of modes in the
 | 
			
		||||
                                      // Mode enumeration class
 | 
			
		||||
  }
 | 
			
		||||
  QVariant data (QModelIndex const&, int role = Qt::DisplayRole) const override;
 | 
			
		||||
  QVariant headerData (int section, Qt::Orientation, int = Qt::DisplayRole) const override;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Q_DECLARE_METATYPE (Modes::Mode);
 | 
			
		||||
 | 
			
		||||
#if !defined (QT_NO_DEBUG_STREAM)
 | 
			
		||||
ENUM_QDEBUG_OPS_DECL (Modes, Mode);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
ENUM_QDATASTREAM_OPS_DECL (Modes, Mode);
 | 
			
		||||
ENUM_CONVERSION_OPS_DECL (Modes, Mode);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										14
									
								
								Radio.cpp
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								Radio.cpp
									
									
									
									
									
								
							@ -2,7 +2,6 @@
 | 
			
		||||
 | 
			
		||||
#include <cmath>
 | 
			
		||||
 | 
			
		||||
#include <QMetaType>
 | 
			
		||||
#include <QString>
 | 
			
		||||
#include <QChar>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
@ -14,19 +13,6 @@ namespace Radio
 | 
			
		||||
{
 | 
			
		||||
  namespace
 | 
			
		||||
  {
 | 
			
		||||
    struct init
 | 
			
		||||
    {
 | 
			
		||||
      init ()
 | 
			
		||||
      {
 | 
			
		||||
        qRegisterMetaType<Frequency> ("Frequency");
 | 
			
		||||
 | 
			
		||||
        qRegisterMetaType<Frequencies> ("Frequencies");
 | 
			
		||||
        qRegisterMetaTypeStreamOperators<Frequencies> ("Frequencies");
 | 
			
		||||
 | 
			
		||||
        qRegisterMetaType<FrequencyDelta> ("FrequencyDelta");
 | 
			
		||||
      }
 | 
			
		||||
    } static_initaializer;
 | 
			
		||||
 | 
			
		||||
    double constexpr MHz_factor {1.e6};
 | 
			
		||||
    int constexpr frequency_precsion {6};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -3,7 +3,6 @@
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QLocale>
 | 
			
		||||
#include <QList>
 | 
			
		||||
 | 
			
		||||
class QVariant;
 | 
			
		||||
class QString;
 | 
			
		||||
@ -18,7 +17,6 @@ namespace Radio
 | 
			
		||||
  // Frequency types
 | 
			
		||||
  //
 | 
			
		||||
  using Frequency = quint64;
 | 
			
		||||
  using Frequencies = QList<Frequency>;
 | 
			
		||||
  using FrequencyDelta = qint64;
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
@ -48,7 +46,6 @@ namespace Radio
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Q_DECLARE_METATYPE (Radio::Frequency);
 | 
			
		||||
Q_DECLARE_METATYPE (Radio::Frequencies);
 | 
			
		||||
Q_DECLARE_METATYPE (Radio::FrequencyDelta);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -19,20 +19,6 @@
 | 
			
		||||
 | 
			
		||||
#include "Bands.hpp"
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
  struct init
 | 
			
		||||
  {
 | 
			
		||||
    init ()
 | 
			
		||||
    {
 | 
			
		||||
      qRegisterMetaType<StationList::Station> ("Station");
 | 
			
		||||
      qRegisterMetaTypeStreamOperators<StationList::Station> ("Station");
 | 
			
		||||
      qRegisterMetaType<StationList::Stations> ("Stations");
 | 
			
		||||
      qRegisterMetaTypeStreamOperators<StationList::Stations> ("Stations");
 | 
			
		||||
    }
 | 
			
		||||
  } static_initializer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if !defined (QT_NO_DEBUG_STREAM)
 | 
			
		||||
QDebug operator << (QDebug debug, StationList::Station const& station)
 | 
			
		||||
{
 | 
			
		||||
@ -70,12 +56,10 @@ public:
 | 
			
		||||
  {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Stations const& stations () const {return stations_;}
 | 
			
		||||
  void assign (Stations);
 | 
			
		||||
  Stations station_list (Stations);
 | 
			
		||||
  QModelIndex add (Station);
 | 
			
		||||
  FrequencyDelta offset (Frequency) const;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
  // Implement the QAbstractTableModel interface.
 | 
			
		||||
  int rowCount (QModelIndex const& parent = QModelIndex {}) const override;
 | 
			
		||||
  int columnCount (QModelIndex const& parent = QModelIndex {}) const override;
 | 
			
		||||
@ -90,7 +74,6 @@ protected:
 | 
			
		||||
  QMimeData * mimeData (QModelIndexList const&) const override;
 | 
			
		||||
  bool dropMimeData (QMimeData const *, Qt::DropAction, int row, int column, QModelIndex const& parent) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  // Helper method for band validation.
 | 
			
		||||
  QModelIndex first_matching_band (QString const& band_name) const
 | 
			
		||||
  {
 | 
			
		||||
@ -127,15 +110,14 @@ StationList::~StationList ()
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
StationList& StationList::operator = (Stations stations)
 | 
			
		||||
auto StationList::station_list (Stations stations) -> Stations
 | 
			
		||||
{
 | 
			
		||||
  m_->assign (stations);
 | 
			
		||||
  return *this;
 | 
			
		||||
  return m_->station_list (stations);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
auto StationList::stations () const -> Stations
 | 
			
		||||
auto StationList::station_list () const -> Stations const&
 | 
			
		||||
{
 | 
			
		||||
  return m_->stations ();
 | 
			
		||||
  return m_->stations_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QModelIndex StationList::add (Station s)
 | 
			
		||||
@ -145,13 +127,11 @@ QModelIndex StationList::add (Station s)
 | 
			
		||||
 | 
			
		||||
bool StationList::remove (Station s)
 | 
			
		||||
{
 | 
			
		||||
  auto row = m_->stations ().indexOf (s);
 | 
			
		||||
 | 
			
		||||
  auto row = m_->stations_.indexOf (s);
 | 
			
		||||
  if (0 > row)
 | 
			
		||||
    {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return removeRow (row);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -194,11 +174,12 @@ auto StationList::offset (Frequency f) const -> FrequencyDelta
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void StationList::impl::assign (Stations stations)
 | 
			
		||||
auto StationList::impl::station_list (Stations stations) -> Stations
 | 
			
		||||
{
 | 
			
		||||
  beginResetModel ();
 | 
			
		||||
  std::swap (stations_, stations);
 | 
			
		||||
  endResetModel ();
 | 
			
		||||
  return stations;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QModelIndex StationList::impl::add (Station s)
 | 
			
		||||
@ -221,22 +202,19 @@ QModelIndex StationList::impl::add (Station s)
 | 
			
		||||
auto StationList::impl::offset (Frequency f) const -> FrequencyDelta
 | 
			
		||||
{
 | 
			
		||||
  // Lookup band for frequency
 | 
			
		||||
  auto band_index = bands_->find (f);
 | 
			
		||||
  if (band_index.isValid ())
 | 
			
		||||
  auto const& band = bands_->find (f);
 | 
			
		||||
  if (band != bands_->out_of_band ())
 | 
			
		||||
    {
 | 
			
		||||
      auto band_name = band_index.data ().toString ();
 | 
			
		||||
 | 
			
		||||
      // Lookup station for band
 | 
			
		||||
      for (int i = 0; i < stations ().size (); ++i)
 | 
			
		||||
      for (int i = 0; i < stations_.size (); ++i)
 | 
			
		||||
        {
 | 
			
		||||
          if (stations_[i].band_name_ == band_name)
 | 
			
		||||
          if (stations_[i].band_name_ == band->name_)
 | 
			
		||||
            {
 | 
			
		||||
              return stations_[i].offset_;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return 0;			// no offset
 | 
			
		||||
  return 0;                     // no offset
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int StationList::impl::rowCount (QModelIndex const& parent) const
 | 
			
		||||
@ -260,7 +238,7 @@ Qt::ItemFlags StationList::impl::flags (QModelIndex const& index) const
 | 
			
		||||
      && row < stations_.size ()
 | 
			
		||||
      && column < num_columns)
 | 
			
		||||
    {
 | 
			
		||||
      if (2 == column)
 | 
			
		||||
      if (description_column == column)
 | 
			
		||||
        {
 | 
			
		||||
          result |= Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
 | 
			
		||||
        }
 | 
			
		||||
@ -289,7 +267,7 @@ QVariant StationList::impl::data (QModelIndex const& index, int role) const
 | 
			
		||||
    {
 | 
			
		||||
      switch (column)
 | 
			
		||||
        {
 | 
			
		||||
        case 0:			// band name
 | 
			
		||||
        case band_column:
 | 
			
		||||
          switch (role)
 | 
			
		||||
            {
 | 
			
		||||
            case SortRole:
 | 
			
		||||
@ -318,19 +296,19 @@ QVariant StationList::impl::data (QModelIndex const& index, int role) const
 | 
			
		||||
            }
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case 1:			// frequency offset
 | 
			
		||||
        case offset_column:
 | 
			
		||||
          {
 | 
			
		||||
            auto frequency_offset = stations_.at (row).offset_;
 | 
			
		||||
            switch (role)
 | 
			
		||||
              {
 | 
			
		||||
              case SortRole:
 | 
			
		||||
              case Qt::EditRole:
 | 
			
		||||
              case Qt::AccessibleTextRole:
 | 
			
		||||
                item = frequency_offset;
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
              case SortRole:
 | 
			
		||||
              case Qt::DisplayRole:
 | 
			
		||||
              case Qt::EditRole:
 | 
			
		||||
                item = frequency_offset;
 | 
			
		||||
                item = Radio::pretty_frequency_MHz_string (frequency_offset) + " MHz";
 | 
			
		||||
                break;
 | 
			
		||||
 | 
			
		||||
              case Qt::ToolTipRole:
 | 
			
		||||
@ -345,7 +323,7 @@ QVariant StationList::impl::data (QModelIndex const& index, int role) const
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case 2:			// antenna description
 | 
			
		||||
        case description_column:
 | 
			
		||||
          switch (role)
 | 
			
		||||
            {
 | 
			
		||||
            case SortRole:
 | 
			
		||||
@ -379,9 +357,9 @@ QVariant StationList::impl::headerData (int section, Qt::Orientation orientation
 | 
			
		||||
    {
 | 
			
		||||
      switch (section)
 | 
			
		||||
        {
 | 
			
		||||
        case 0: header = tr ("Band"); break;
 | 
			
		||||
        case 1: header = tr ("Offset"); break;
 | 
			
		||||
        case 2: header = tr ("Antenna Description"); break;
 | 
			
		||||
        case band_column: header = tr ("Band"); break;
 | 
			
		||||
        case offset_column: header = tr ("Offset"); break;
 | 
			
		||||
        case description_column: header = tr ("Antenna Description"); break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
@ -407,7 +385,7 @@ bool StationList::impl::setData (QModelIndex const& model_index, QVariant const&
 | 
			
		||||
 | 
			
		||||
      switch (model_index.column ())
 | 
			
		||||
        {
 | 
			
		||||
        case 0:
 | 
			
		||||
        case band_column:
 | 
			
		||||
          {
 | 
			
		||||
            // Check if band name is valid.
 | 
			
		||||
            auto band_index = first_matching_band (value.toString ());
 | 
			
		||||
@ -420,7 +398,7 @@ bool StationList::impl::setData (QModelIndex const& model_index, QVariant const&
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case 1:
 | 
			
		||||
        case offset_column:
 | 
			
		||||
          {
 | 
			
		||||
            stations_[row].offset_ = value.value<FrequencyDelta> ();
 | 
			
		||||
            Q_EMIT dataChanged (model_index, model_index, roles);
 | 
			
		||||
@ -428,7 +406,7 @@ bool StationList::impl::setData (QModelIndex const& model_index, QVariant const&
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
 | 
			
		||||
        case 2:
 | 
			
		||||
        case description_column:
 | 
			
		||||
          stations_[row].antenna_description_ = value.toString ();
 | 
			
		||||
          Q_EMIT dataChanged (model_index, model_index, roles);
 | 
			
		||||
          changed = true;
 | 
			
		||||
@ -508,9 +486,8 @@ bool StationList::impl::dropMimeData (QMimeData const * data, Qt::DropAction act
 | 
			
		||||
    {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  if (parent.isValid ()
 | 
			
		||||
      && 2 == parent.column ()
 | 
			
		||||
      && description_column == parent.column ()
 | 
			
		||||
      && data->hasFormat (mime_type))
 | 
			
		||||
    {
 | 
			
		||||
      QByteArray encoded_data {data->data (mime_type)};
 | 
			
		||||
@ -534,17 +511,16 @@ bool StationList::impl::dropMimeData (QMimeData const * data, Qt::DropAction act
 | 
			
		||||
          QString frequency_string;
 | 
			
		||||
          stream >> frequency_string;
 | 
			
		||||
          auto frequency = Radio::frequency (frequency_string, 0);
 | 
			
		||||
          auto band_index = bands_->find (frequency);
 | 
			
		||||
          auto const& band = bands_->find (frequency);
 | 
			
		||||
          if (stations_.cend () == std::find_if (stations_.cbegin ()
 | 
			
		||||
                                                 , stations_.cend ()
 | 
			
		||||
                                                 , [&band_index] (Station const& s) {return s.band_name_ == band_index.data ().toString ();}))
 | 
			
		||||
                                                 , [&band] (Station const& s) {return s.band_name_ == band->name_;}))
 | 
			
		||||
            {
 | 
			
		||||
              add (Station {band_index.data ().toString (), 0, QString {}});
 | 
			
		||||
              // not found so add it
 | 
			
		||||
              add (Station {band->name_, 0, QString {}});
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -59,13 +59,15 @@ public:
 | 
			
		||||
 | 
			
		||||
  using Stations = QList<Station>;
 | 
			
		||||
 | 
			
		||||
  enum Column {band_column, offset_column, description_column};
 | 
			
		||||
 | 
			
		||||
  explicit StationList (Bands const * bands, QObject * parent = nullptr);
 | 
			
		||||
  explicit StationList (Bands const * bands, Stations, QObject * parent = nullptr);
 | 
			
		||||
  ~StationList ();
 | 
			
		||||
 | 
			
		||||
  // Load and store contents.
 | 
			
		||||
  StationList& operator = (Stations);
 | 
			
		||||
  Stations stations () const;
 | 
			
		||||
  // Load and query contents.
 | 
			
		||||
  Stations station_list (Stations);
 | 
			
		||||
  Stations const& station_list () const;
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // Model API
 | 
			
		||||
@ -83,10 +85,6 @@ private:
 | 
			
		||||
  pimpl<impl> m_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if !defined (QT_NO_DEBUG_STREAM)
 | 
			
		||||
QDebug operator << (QDebug debug, StationList::Station const&);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Station equivalence
 | 
			
		||||
inline
 | 
			
		||||
bool operator == (StationList::Station const& lhs, StationList::Station const& rhs)
 | 
			
		||||
@ -96,6 +94,13 @@ bool operator == (StationList::Station const& lhs, StationList::Station const& r
 | 
			
		||||
    && lhs.antenna_description_ == rhs.antenna_description_;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QDataStream& operator << (QDataStream&, StationList::Station const&);
 | 
			
		||||
QDataStream& operator >> (QDataStream&, StationList::Station&);
 | 
			
		||||
 | 
			
		||||
#if !defined (QT_NO_DEBUG_STREAM)
 | 
			
		||||
QDebug operator << (QDebug debug, StationList::Station const&);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
Q_DECLARE_METATYPE (StationList::Station);
 | 
			
		||||
Q_DECLARE_METATYPE (StationList::Stations);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,18 +2,6 @@
 | 
			
		||||
 | 
			
		||||
#include "moc_Transceiver.cpp"
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
  struct init
 | 
			
		||||
  {
 | 
			
		||||
    init ()
 | 
			
		||||
    {
 | 
			
		||||
      qRegisterMetaType<Transceiver::TransceiverState> ("Transceiver::TransceiverState");
 | 
			
		||||
      qRegisterMetaType<Transceiver::MODE> ("Transceiver::MODE");
 | 
			
		||||
    }
 | 
			
		||||
  } static_initialization;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if !defined (QT_NO_DEBUG_STREAM)
 | 
			
		||||
 | 
			
		||||
ENUM_QDEBUG_OPS_IMPL (Transceiver, MODE);
 | 
			
		||||
 | 
			
		||||
@ -21,25 +21,6 @@ char const * const TransceiverFactory::basic_transceiver_name_ = "None";
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
  struct init
 | 
			
		||||
  {
 | 
			
		||||
    init ()
 | 
			
		||||
    {
 | 
			
		||||
      qRegisterMetaType<TransceiverFactory::DataBits> ("TransceiverFactory::DataBits");
 | 
			
		||||
      qRegisterMetaTypeStreamOperators<TransceiverFactory::DataBits> ("TransceiverFactory::DataBits");
 | 
			
		||||
      qRegisterMetaType<TransceiverFactory::StopBits> ("TransceiverFactory::StopBits");
 | 
			
		||||
      qRegisterMetaTypeStreamOperators<TransceiverFactory::StopBits> ("TransceiverFactory::StopBits");
 | 
			
		||||
      qRegisterMetaType<TransceiverFactory::Handshake> ("TransceiverFactory::Handshake");
 | 
			
		||||
      qRegisterMetaTypeStreamOperators<TransceiverFactory::Handshake> ("TransceiverFactory::Handshake");
 | 
			
		||||
      qRegisterMetaType<TransceiverFactory::PTTMethod> ("TransceiverFactory::PTTMethod");
 | 
			
		||||
      qRegisterMetaTypeStreamOperators<TransceiverFactory::PTTMethod> ("TransceiverFactory::PTTMethod");
 | 
			
		||||
      qRegisterMetaType<TransceiverFactory::TXAudioSource> ("TransceiverFactory::TXAudioSource");
 | 
			
		||||
      qRegisterMetaTypeStreamOperators<TransceiverFactory::TXAudioSource> ("TransceiverFactory::TXAudioSource");
 | 
			
		||||
      qRegisterMetaType<TransceiverFactory::SplitMode> ("TransceiverFactory::SplitMode");
 | 
			
		||||
      qRegisterMetaTypeStreamOperators<TransceiverFactory::SplitMode> ("TransceiverFactory::SplitMode");
 | 
			
		||||
    }
 | 
			
		||||
  } static_initializer;
 | 
			
		||||
 | 
			
		||||
  enum				// supported non-hamlib radio interfaces
 | 
			
		||||
    {
 | 
			
		||||
      NonHamlibBaseId = 9899
 | 
			
		||||
 | 
			
		||||
@ -33,14 +33,6 @@ namespace
 | 
			
		||||
{
 | 
			
		||||
  int constexpr points {256};
 | 
			
		||||
 | 
			
		||||
  struct init
 | 
			
		||||
  {
 | 
			
		||||
    init ()
 | 
			
		||||
    {
 | 
			
		||||
      qRegisterMetaTypeStreamOperators<WFPalette::Colours> ("Colours");
 | 
			
		||||
    }
 | 
			
		||||
  } static_initaializer;
 | 
			
		||||
 | 
			
		||||
  using Colours = WFPalette::Colours;
 | 
			
		||||
 | 
			
		||||
  // ensure that palette colours are useable for interpolation
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								main.cpp
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								main.cpp
									
									
									
									
									
								
							@ -23,7 +23,7 @@
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "revision_utils.hpp"
 | 
			
		||||
 | 
			
		||||
#include "MetaDataRegistry.hpp"
 | 
			
		||||
#include "SettingsGroup.hpp"
 | 
			
		||||
#include "TraceFile.hpp"
 | 
			
		||||
#include "mainwindow.h"
 | 
			
		||||
@ -31,6 +31,8 @@
 | 
			
		||||
 | 
			
		||||
int main(int argc, char *argv[])
 | 
			
		||||
{
 | 
			
		||||
  register_types ();            // make the Qt magic happen
 | 
			
		||||
 | 
			
		||||
  // Multiple instances:
 | 
			
		||||
  QSharedMemory mem_jt9;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										196
									
								
								mainwindow.cpp
									
									
									
									
									
								
							
							
						
						
									
										196
									
								
								mainwindow.cpp
									
									
									
									
									
								
							@ -61,27 +61,6 @@ namespace
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class BandAndFrequencyItemDelegate final
 | 
			
		||||
  : public QStyledItemDelegate
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  explicit BandAndFrequencyItemDelegate (Bands const * bands, QObject * parent = nullptr)
 | 
			
		||||
    : QStyledItemDelegate {parent}
 | 
			
		||||
    , bands_ {bands}
 | 
			
		||||
  {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  QString displayText (QVariant const& v, QLocale const&) const override
 | 
			
		||||
  {
 | 
			
		||||
    return Radio::pretty_frequency_MHz_string (Radio::frequency (v, 6))
 | 
			
		||||
      + QChar::Nbsp
 | 
			
		||||
      + '(' + (bands_->data (bands_->find (Radio::frequency (v, 6)))).toString () + ')';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  Bands const * bands_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//--------------------------------------------------- MainWindow constructor
 | 
			
		||||
MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdmem,
 | 
			
		||||
                       unsigned downSampleFactor, QWidget *parent) :
 | 
			
		||||
@ -278,15 +257,11 @@ MainWindow::MainWindow(bool multiple, QSettings * settings, QSharedMemory *shdme
 | 
			
		||||
 | 
			
		||||
  // Hook up working frequencies.
 | 
			
		||||
  ui->bandComboBox->setModel (m_config.frequencies ());
 | 
			
		||||
  ui->bandComboBox->setModelColumn (1); // MHz
 | 
			
		||||
  ui->bandComboBox->setModelColumn (FrequencyList::frequency_mhz_column);
 | 
			
		||||
 | 
			
		||||
  // Add delegate to show bands alongside frequencies in combo box
 | 
			
		||||
  // popup list.
 | 
			
		||||
  ui->bandComboBox->view ()->setItemDelegateForColumn (1, new BandAndFrequencyItemDelegate {m_config.bands (), this});
 | 
			
		||||
 | 
			
		||||
  // combo box drop downs are limited to the drop down selector width,
 | 
			
		||||
  // this almost random increase improves the situation
 | 
			
		||||
  ui->bandComboBox->view ()->setMinimumWidth (ui->bandComboBox->view ()->sizeHintForColumn (1) + 40);
 | 
			
		||||
  // combo box drop down width defaults to the line edit + decorator width,
 | 
			
		||||
  // here we change that to the column width size hint of the model column
 | 
			
		||||
  ui->bandComboBox->view ()->setMinimumWidth (ui->bandComboBox->view ()->sizeHintForColumn (FrequencyList::frequency_mhz_column));
 | 
			
		||||
 | 
			
		||||
  // Enable live band combo box entry validation and action.
 | 
			
		||||
  auto band_validator = new LiveFrequencyValidator {ui->bandComboBox
 | 
			
		||||
@ -646,7 +621,6 @@ void MainWindow::writeSettings()
 | 
			
		||||
  m_settings->setValue("GUItab",ui->tabWidget->currentIndex());
 | 
			
		||||
  m_settings->setValue("OutBufSize",outBufSize);
 | 
			
		||||
  m_settings->setValue("LockTxFreq",m_lockTxFreq);
 | 
			
		||||
  m_settings->setValue("Plus2kHz",m_plus2kHz);
 | 
			
		||||
  m_settings->setValue("PctTx",m_pctx);
 | 
			
		||||
  m_settings->setValue("dBm",m_dBm);
 | 
			
		||||
  m_settings->setValue("UploadSpots",m_uploadSpots);
 | 
			
		||||
@ -736,8 +710,6 @@ void MainWindow::readSettings()
 | 
			
		||||
  outBufSize=m_settings->value("OutBufSize",4096).toInt();
 | 
			
		||||
  m_lockTxFreq=m_settings->value("LockTxFreq",false).toBool();
 | 
			
		||||
  ui->cbTxLock->setChecked(m_lockTxFreq);
 | 
			
		||||
  m_plus2kHz=m_settings->value("Plus2kHz",false).toBool();
 | 
			
		||||
  ui->cbPlus2kHz->setChecked(m_plus2kHz);
 | 
			
		||||
  ui->sunriseBands->setText(m_settings->value("SunriseBands","").toString());
 | 
			
		||||
  on_sunriseBands_editingFinished();
 | 
			
		||||
  ui->dayBands->setText(m_settings->value("DayBands","").toString());
 | 
			
		||||
@ -1176,29 +1148,33 @@ void MainWindow::qsy (Frequency f)
 | 
			
		||||
void MainWindow::displayDialFrequency ()
 | 
			
		||||
{
 | 
			
		||||
  // lookup band
 | 
			
		||||
  auto bands_model = m_config.bands ();
 | 
			
		||||
  QString t {bands_model->data(bands_model->find(m_dialFreq)).toString()};
 | 
			
		||||
  ui->bandComboBox->setCurrentText (t);
 | 
			
		||||
  m_wideGraph->setRxBand(t);
 | 
			
		||||
  auto const& band_name = m_config.bands ()->find (m_dialFreq)->name_;
 | 
			
		||||
  ui->bandComboBox->setCurrentText (band_name);
 | 
			
		||||
  m_wideGraph->setRxBand (band_name);
 | 
			
		||||
 | 
			
		||||
  // search working frequencies for one we are within 10kHz of
 | 
			
		||||
  auto frequencies = m_config.frequencies ();
 | 
			
		||||
  // search working frequencies for one we are within 10kHz of (1 Mhz
 | 
			
		||||
  // of on VHF and up)
 | 
			
		||||
  bool valid {false};
 | 
			
		||||
  quint64 min_offset=99999999;
 | 
			
		||||
 | 
			
		||||
  for (int row = 0; row < frequencies->rowCount (); ++row) {
 | 
			
		||||
  quint64 min_offset {99999999};
 | 
			
		||||
  auto const& frequencies = m_config.frequencies ();
 | 
			
		||||
  for (int row = 0; row < frequencies->rowCount (); ++row)
 | 
			
		||||
    {
 | 
			
		||||
      auto const& source_row = frequencies->mapToSource (frequencies->index (row, 0)).row ();
 | 
			
		||||
      auto const& item = frequencies->frequency_list ()[source_row];
 | 
			
		||||
      // we need to do specific checks for above and below here to
 | 
			
		||||
      // ensure that we can use unsigned Radio::Frequency since we
 | 
			
		||||
      // potentially use the full 64-bit unsigned range.
 | 
			
		||||
      auto working_frequency = frequencies->data (frequencies->index (row, 0)).value<Frequency> ();
 | 
			
		||||
      auto offset = m_dialFreq > working_frequency ? m_dialFreq - working_frequency : working_frequency - m_dialFreq;
 | 
			
		||||
      if(offset<min_offset) {
 | 
			
		||||
         m_freqNominal=working_frequency;
 | 
			
		||||
         min_offset=offset;
 | 
			
		||||
      auto const& working_frequency = item.frequency_;
 | 
			
		||||
      auto const& offset = m_dialFreq > working_frequency ? m_dialFreq - working_frequency : working_frequency - m_dialFreq;
 | 
			
		||||
      if (offset < min_offset) {
 | 
			
		||||
         m_freqNominal = working_frequency;
 | 
			
		||||
         min_offset = offset;
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
  if ((min_offset < 10000u) or (m_config.enable_VHF_features() and
 | 
			
		||||
                                min_offset < 1000000u)) valid = true;
 | 
			
		||||
  if (min_offset < 10000u or (m_config.enable_VHF_features() and
 | 
			
		||||
                              min_offset < 1000000u)) {
 | 
			
		||||
    valid = true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ui->labDialFreq->setProperty ("oob", !valid);
 | 
			
		||||
  // the following sequence is necessary to update the style
 | 
			
		||||
@ -1672,15 +1648,16 @@ void MainWindow::readFromStdout()                             //readFromStdout
 | 
			
		||||
        msgBox("Cannot open \"" + f.fileName () + "\" for append:" + f.errorString ());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (m_config.insert_blank () && m_blankLine) {
 | 
			
		||||
        QString band;
 | 
			
		||||
        if (QDateTime::currentMSecsSinceEpoch() / 1000 - m_secBandChanged > 50) {
 | 
			
		||||
          auto const& bands_model = m_config.bands ();
 | 
			
		||||
          band = ' ' + bands_model->data (bands_model->find (m_dialFreq + ui->TxFreqSpinBox->value ())).toString ();
 | 
			
		||||
        }
 | 
			
		||||
        ui->decodedTextBrowser->insertLineSpacer (band.rightJustified  (40, '-'));
 | 
			
		||||
        m_blankLine = false;
 | 
			
		||||
      }
 | 
			
		||||
        if (m_config.insert_blank () && m_blankLine)
 | 
			
		||||
          {
 | 
			
		||||
            QString band;
 | 
			
		||||
            if (QDateTime::currentMSecsSinceEpoch() / 1000 - m_secBandChanged > 50)
 | 
			
		||||
              {
 | 
			
		||||
                band = ' ' + QString {m_config.bands ()->find (m_dialFreq)->name_};
 | 
			
		||||
              }
 | 
			
		||||
            ui->decodedTextBrowser->insertLineSpacer (band.rightJustified  (40, '-'));
 | 
			
		||||
            m_blankLine = false;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
      DecodedText decodedtext;
 | 
			
		||||
      decodedtext = t.replace("\n",""); //t.replace("\n","").mid(0,t.length()-4);
 | 
			
		||||
@ -2251,9 +2228,8 @@ void MainWindow::startTx2()
 | 
			
		||||
    transmit (snr);
 | 
			
		||||
    signalMeter->setValue(0);
 | 
			
		||||
    if(m_mode.mid(0,4)=="WSPR" and !m_tune) {
 | 
			
		||||
      auto const& bands_model = m_config.bands ();
 | 
			
		||||
      t = " Transmiting " + m_mode + " ----------------------- " +
 | 
			
		||||
          bands_model->data(bands_model->find(m_dialFreq)).toString ();
 | 
			
		||||
        m_config.bands ()->find (m_dialFreq)->name_;
 | 
			
		||||
      ui->decodedTextBrowser->append(t.rightJustified (71, '-'));
 | 
			
		||||
 | 
			
		||||
      QFile f {m_dataDir.absoluteFilePath ("ALL_WSPR.TXT")};
 | 
			
		||||
@ -2986,10 +2962,8 @@ void MainWindow::acceptQSO2(QDateTime const& QSO_date, QString const& call, QStr
 | 
			
		||||
                            , QString const& tx_power, QString const& comments
 | 
			
		||||
                            , QString const& name)
 | 
			
		||||
{
 | 
			
		||||
  auto const& bands_model = m_config.bands ();
 | 
			
		||||
  auto band = bands_model->data (bands_model->find (m_dialFreq + ui->TxFreqSpinBox->value ())).toString ();
 | 
			
		||||
  QString date = m_dateTimeQSO.toString("yyyyMMdd");
 | 
			
		||||
  m_logBook.addAsWorked(m_hisCall,band,m_modeTx,date);
 | 
			
		||||
  m_logBook.addAsWorked (m_hisCall, m_config.bands ()->find (m_dialFreq)->name_, m_modeTx, date);
 | 
			
		||||
 | 
			
		||||
  m_messageClient->qso_logged (QSO_date, call, grid, dial_freq, mode, rpt_sent, rpt_received, tx_power, comments, name);
 | 
			
		||||
 | 
			
		||||
@ -3009,6 +2983,7 @@ void MainWindow::acceptQSO2(QDateTime const& QSO_date, QString const& call, QStr
 | 
			
		||||
void MainWindow::on_actionJT9_1_triggered()
 | 
			
		||||
{
 | 
			
		||||
  m_mode="JT9";
 | 
			
		||||
  switch_mode (Modes::JT9);
 | 
			
		||||
  if(m_modeTx!="JT9") on_pbTxMode_clicked();
 | 
			
		||||
  statusChanged();
 | 
			
		||||
  m_TRperiod=60;
 | 
			
		||||
@ -3036,6 +3011,7 @@ void MainWindow::on_actionJT9_1_triggered()
 | 
			
		||||
void MainWindow::on_actionJT9W_1_triggered()
 | 
			
		||||
{
 | 
			
		||||
  m_mode="JT9W-1";
 | 
			
		||||
  switch_mode (Modes::JT9W_1);
 | 
			
		||||
  if(m_modeTx!="JT9") on_pbTxMode_clicked();
 | 
			
		||||
  statusChanged();
 | 
			
		||||
  m_TRperiod=60;
 | 
			
		||||
@ -3068,6 +3044,7 @@ void MainWindow::on_actionJT65_triggered()
 | 
			
		||||
    on_pbTxMode_clicked();
 | 
			
		||||
  }
 | 
			
		||||
  m_mode="JT65";
 | 
			
		||||
  switch_mode (Modes::JT65);
 | 
			
		||||
  if(m_modeTx!="JT65") on_pbTxMode_clicked();
 | 
			
		||||
  statusChanged();
 | 
			
		||||
  m_TRperiod=60;
 | 
			
		||||
@ -3105,6 +3082,7 @@ void MainWindow::on_actionJT65_triggered()
 | 
			
		||||
void MainWindow::on_actionJT9_JT65_triggered()
 | 
			
		||||
{
 | 
			
		||||
  m_mode="JT9+JT65";
 | 
			
		||||
  switch_mode (Modes::JT65);
 | 
			
		||||
  if(m_modeTx != "JT65") m_modeTx="JT9";
 | 
			
		||||
  m_nSubMode=0;                    //Dual-mode always means JT9 and JT65A
 | 
			
		||||
  statusChanged();
 | 
			
		||||
@ -3133,6 +3111,7 @@ void MainWindow::on_actionJT9_JT65_triggered()
 | 
			
		||||
void MainWindow::on_actionJT4_triggered()
 | 
			
		||||
{
 | 
			
		||||
  m_mode="JT4";
 | 
			
		||||
  switch_mode (Modes::JT4);
 | 
			
		||||
  m_modeTx="JT4";
 | 
			
		||||
  statusChanged();
 | 
			
		||||
  m_TRperiod=60;
 | 
			
		||||
@ -3171,6 +3150,7 @@ void MainWindow::on_actionJT4_triggered()
 | 
			
		||||
void MainWindow::on_actionWSPR_2_triggered()
 | 
			
		||||
{
 | 
			
		||||
  m_mode="WSPR-2";
 | 
			
		||||
  switch_mode (Modes::WSPR);
 | 
			
		||||
  m_modeTx="WSPR-2";                                    //### not needed ?? ###
 | 
			
		||||
  statusChanged();
 | 
			
		||||
  m_TRperiod=120;
 | 
			
		||||
@ -3194,8 +3174,20 @@ void MainWindow::on_actionWSPR_2_triggered()
 | 
			
		||||
void MainWindow::on_actionWSPR_15_triggered()
 | 
			
		||||
{
 | 
			
		||||
  msgBox("WSPR-15 is not yet available");
 | 
			
		||||
  switch_mode (Modes::WSPR);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::switch_mode (Mode mode)
 | 
			
		||||
{
 | 
			
		||||
  auto f = m_dialFreq;
 | 
			
		||||
  m_config.frequencies ()->filter (mode);
 | 
			
		||||
  auto const& index = m_config.frequencies ()->best_working_frequency (f, mode);
 | 
			
		||||
  if (index.isValid ())
 | 
			
		||||
    {
 | 
			
		||||
      ui->bandComboBox->setCurrentIndex (index.row ());
 | 
			
		||||
      on_bandComboBox_activated (index.row ());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::WSPR_config(bool b)
 | 
			
		||||
{
 | 
			
		||||
@ -3328,26 +3320,44 @@ bool MainWindow::gridOK(QString g)
 | 
			
		||||
  return b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::on_bandComboBox_currentIndexChanged (int index)
 | 
			
		||||
{
 | 
			
		||||
  auto const& frequencies = m_config.frequencies ();
 | 
			
		||||
  auto const& source_index = frequencies->mapToSource (frequencies->index (index, FrequencyList::frequency_column));
 | 
			
		||||
  Frequency frequency {m_dialFreq};
 | 
			
		||||
  if (source_index.isValid ())
 | 
			
		||||
    {
 | 
			
		||||
      frequency = frequencies->frequency_list ()[source_index.row ()].frequency_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  // Lookup band
 | 
			
		||||
  auto const& band  = m_config.bands ()->find (frequency);
 | 
			
		||||
  auto const& out_of_band  = m_config.bands ()->out_of_band ();
 | 
			
		||||
  if (out_of_band != band)
 | 
			
		||||
    {
 | 
			
		||||
      ui->bandComboBox->lineEdit ()->setStyleSheet ({});
 | 
			
		||||
      ui->bandComboBox->setCurrentText (band->name_);
 | 
			
		||||
    }
 | 
			
		||||
  else
 | 
			
		||||
    {
 | 
			
		||||
      ui->bandComboBox->lineEdit ()->setStyleSheet ("QLineEdit {color: yellow; background-color : red;}");
 | 
			
		||||
      ui->bandComboBox->setCurrentText (out_of_band->name_);
 | 
			
		||||
    }
 | 
			
		||||
  displayDialFrequency ();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::on_bandComboBox_activated (int index)
 | 
			
		||||
{
 | 
			
		||||
  auto frequencies = m_config.frequencies ();
 | 
			
		||||
  auto frequency = frequencies->data (frequencies->index (index, 0));
 | 
			
		||||
  // Lookup band
 | 
			
		||||
  auto bands = m_config.bands ();
 | 
			
		||||
  auto band_index = bands->find (frequency);
 | 
			
		||||
  if (band_index.isValid ()) {
 | 
			
		||||
    ui->bandComboBox->lineEdit ()->setStyleSheet ({});
 | 
			
		||||
    ui->bandComboBox->setCurrentText (band_index.data ().toString ());
 | 
			
		||||
  } else {
 | 
			
		||||
    ui->bandComboBox->lineEdit ()->setStyleSheet ("QLineEdit {color: yellow; background-color : red;}");
 | 
			
		||||
    ui->bandComboBox->setCurrentText (bands->data (QModelIndex {}).toString ());
 | 
			
		||||
  }
 | 
			
		||||
  auto f = frequency.value<Frequency> ();
 | 
			
		||||
  if (m_plus2kHz) f += 2000;
 | 
			
		||||
  auto const& frequencies = m_config.frequencies ();
 | 
			
		||||
  auto const& source_index = frequencies->mapToSource (frequencies->index (index, FrequencyList::frequency_column));
 | 
			
		||||
  Frequency frequency {m_dialFreq};
 | 
			
		||||
  if (source_index.isValid ())
 | 
			
		||||
    {
 | 
			
		||||
      frequency = frequencies->frequency_list ()[source_index.row ()].frequency_;
 | 
			
		||||
    }
 | 
			
		||||
  m_bandEdited = true;
 | 
			
		||||
  band_changed (f);
 | 
			
		||||
  m_wideGraph->setRxBand(band_index.data().toString());
 | 
			
		||||
//  qDebug() << "bandComboBox_activated" << index << 0.000001*f;
 | 
			
		||||
  band_changed (frequency);
 | 
			
		||||
  m_wideGraph->setRxBand (m_config.bands ()->find (frequency)->name_);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::band_changed (Frequency f)
 | 
			
		||||
@ -3607,23 +3617,6 @@ void MainWindow::on_cbTxLock_clicked(bool checked)
 | 
			
		||||
  if(m_lockTxFreq) on_pbR2T_clicked();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::on_cbPlus2kHz_toggled(bool checked)
 | 
			
		||||
{
 | 
			
		||||
  m_plus2kHz = checked;
 | 
			
		||||
 | 
			
		||||
  if (m_config.transceiver_online (false)) { // update state only if not starting up
 | 
			
		||||
      psk_Reporter->sendReport();    // Upload any queued spots before changing band
 | 
			
		||||
      auto f = m_dialFreq;
 | 
			
		||||
      if (m_plus2kHz) {
 | 
			
		||||
        f += 2000;
 | 
			
		||||
      } else {
 | 
			
		||||
        f -= 2000;
 | 
			
		||||
      }
 | 
			
		||||
      m_bandEdited = true;
 | 
			
		||||
      band_changed (f);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MainWindow::handle_transceiver_update (Transceiver::TransceiverState s)
 | 
			
		||||
{
 | 
			
		||||
  transmitDisplay (s.ptt ());
 | 
			
		||||
@ -3868,9 +3861,6 @@ void MainWindow::transmitDisplay (bool transmitting)
 | 
			
		||||
      ui->cbTxLock->setEnabled (QSY_allowed);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
      // Allow +2kHz only when not transmitting or if TX QSYs are allowed
 | 
			
		||||
    ui->cbPlus2kHz->setEnabled (!transmitting || m_config.tx_QSY_allowed ());
 | 
			
		||||
 | 
			
		||||
      // the following are always disallowed in transmit
 | 
			
		||||
    ui->menuMode->setEnabled (!transmitting);
 | 
			
		||||
    ui->bandComboBox->setEnabled (!transmitting);
 | 
			
		||||
@ -4173,9 +4163,8 @@ void MainWindow::p1ReadFromStdout()                        //p1readFromStdout
 | 
			
		||||
 | 
			
		||||
      if (m_config.insert_blank () && m_blankLine) {
 | 
			
		||||
        QString band;
 | 
			
		||||
        auto const& bands_model = m_config.bands ();
 | 
			
		||||
        Frequency f=1000000.0*rxFields.at(3).toDouble()+0.5;
 | 
			
		||||
        band = ' ' + bands_model->data (bands_model->find (f)).toString ();
 | 
			
		||||
        band = ' ' + m_config.bands ()->find (f)->name_;
 | 
			
		||||
        ui->decodedTextBrowser->append(band.rightJustified (71, '-'));
 | 
			
		||||
        m_blankLine = false;
 | 
			
		||||
      }
 | 
			
		||||
@ -4355,10 +4344,9 @@ void MainWindow::bandHopping()
 | 
			
		||||
 | 
			
		||||
  m_band00=iband;
 | 
			
		||||
  auto frequencies = m_config.frequencies ();
 | 
			
		||||
  for (int i=0; i<99; i++) {
 | 
			
		||||
    auto frequency=frequencies->data (frequencies->index (i, 0));
 | 
			
		||||
  for (int row = 0; row < frequencies->rowCount (); ++row) {
 | 
			
		||||
    auto frequency=frequencies->data (frequencies->index (row, FrequencyList::frequency_column));
 | 
			
		||||
    auto f = frequency.value<Frequency>();
 | 
			
		||||
    if(f==0) break;
 | 
			
		||||
    if(f==f0) {
 | 
			
		||||
      on_bandComboBox_activated(i);                        //Set new band
 | 
			
		||||
//      qDebug() << nhr << nmin << int(sec) << "Band selected" << i << 0.000001*f0 << 0.000001*f;
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,7 @@
 | 
			
		||||
#include "soundout.h"
 | 
			
		||||
#include "commons.h"
 | 
			
		||||
#include "Radio.hpp"
 | 
			
		||||
#include "Modes.hpp"
 | 
			
		||||
#include "Configuration.hpp"
 | 
			
		||||
#include "Transceiver.hpp"
 | 
			
		||||
#include "psk_reporter.h"
 | 
			
		||||
@ -65,6 +66,7 @@ class MainWindow : public QMainWindow
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  using Frequency = Radio::Frequency;
 | 
			
		||||
  using Mode = Modes::Mode;
 | 
			
		||||
 | 
			
		||||
  // Multiple instances: call MainWindow() with *thekey
 | 
			
		||||
  explicit MainWindow(bool multiple, QSettings *, QSharedMemory *shdmem,
 | 
			
		||||
@ -176,12 +178,12 @@ private slots:
 | 
			
		||||
                  , QString const& rpt_sent, QString const& rpt_received
 | 
			
		||||
                  , QString const& tx_power, QString const& comments
 | 
			
		||||
                  , QString const& name);
 | 
			
		||||
  void on_bandComboBox_currentIndexChanged (int index);
 | 
			
		||||
  void on_bandComboBox_activated (int index);
 | 
			
		||||
  void on_readFreq_clicked();
 | 
			
		||||
  void on_pbTxMode_clicked();
 | 
			
		||||
  void on_RxFreqSpinBox_valueChanged(int n);
 | 
			
		||||
  void on_cbTxLock_clicked(bool checked);
 | 
			
		||||
  void on_cbPlus2kHz_toggled(bool checked);
 | 
			
		||||
  void on_outAttenuation_valueChanged (int);
 | 
			
		||||
  void rigOpen ();
 | 
			
		||||
  void handle_transceiver_update (Transceiver::TransceiverState);
 | 
			
		||||
@ -233,8 +235,6 @@ private slots:
 | 
			
		||||
  void on_graylineDuration_editingFinished();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  void enable_DXCC_entity (bool on);
 | 
			
		||||
 | 
			
		||||
  Q_SIGNAL void initializeAudioOutputStream (QAudioDeviceInfo,
 | 
			
		||||
      unsigned channels, unsigned msBuffered) const;
 | 
			
		||||
  Q_SIGNAL void stopAudioOutputStream () const;
 | 
			
		||||
@ -370,7 +370,6 @@ private:
 | 
			
		||||
  bool    m_lockTxFreq;
 | 
			
		||||
  bool    m_tx2QSO;
 | 
			
		||||
  bool    m_CATerror;
 | 
			
		||||
  bool    m_plus2kHz;
 | 
			
		||||
  bool    m_bAstroData;
 | 
			
		||||
  bool    m_bEME;
 | 
			
		||||
  bool    m_bShMsgs;
 | 
			
		||||
@ -507,6 +506,8 @@ private:
 | 
			
		||||
  void replyToCQ (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text);
 | 
			
		||||
  void replayDecodes ();
 | 
			
		||||
  void postDecode (bool is_new, QString const& message);
 | 
			
		||||
  void enable_DXCC_entity (bool on);
 | 
			
		||||
  void switch_mode (Mode);
 | 
			
		||||
  void bandHopping();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1348,16 +1348,6 @@
 | 
			
		||||
          </property>
 | 
			
		||||
         </widget>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item row="1" column="0">
 | 
			
		||||
         <widget class="QCheckBox" name="cbPlus2kHz">
 | 
			
		||||
          <property name="toolTip">
 | 
			
		||||
           <string>Add 2 kHz to requested dial frequency</string>
 | 
			
		||||
          </property>
 | 
			
		||||
          <property name="text">
 | 
			
		||||
           <string>+2 kHz</string>
 | 
			
		||||
          </property>
 | 
			
		||||
         </widget>
 | 
			
		||||
        </item>
 | 
			
		||||
        <item row="1" column="2">
 | 
			
		||||
         <widget class="QPushButton" name="readFreq">
 | 
			
		||||
          <property name="maximumSize">
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user