mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-21 11:31:51 -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;
|
||||
|
389
Bands.cpp
389
Bands.cpp
@ -1,196 +1,193 @@
|
||||
#include "Bands.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
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},
|
||||
};
|
||||
|
||||
auto constexpr out_of_band = "OOB";
|
||||
|
||||
int constexpr table_rows ()
|
||||
{
|
||||
return sizeof (ADIF_bands) / sizeof (ADIF_bands[0]);
|
||||
}
|
||||
}
|
||||
|
||||
Bands::Bands (QObject * parent)
|
||||
: QAbstractTableModel {parent}
|
||||
{
|
||||
}
|
||||
|
||||
QModelIndex Bands::find (QVariant const& v) 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) {
|
||||
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 QModelIndex {};
|
||||
}
|
||||
|
||||
int Bands::rowCount (QModelIndex const& parent) const
|
||||
{
|
||||
return parent.isValid () ? 0 : table_rows ();
|
||||
}
|
||||
|
||||
int Bands::columnCount (QModelIndex const& parent) const
|
||||
{
|
||||
return parent.isValid () ? 0 : 3;
|
||||
}
|
||||
|
||||
Qt::ItemFlags Bands::flags (QModelIndex const& index) const
|
||||
{
|
||||
return QAbstractTableModel::flags (index) | Qt::ItemIsDropEnabled;
|
||||
}
|
||||
|
||||
QVariant Bands::data (QModelIndex const& index, int role) const
|
||||
{
|
||||
QVariant item;
|
||||
|
||||
if (!index.isValid ())
|
||||
{
|
||||
// Hijack root for OOB string.
|
||||
if (Qt::DisplayRole == role)
|
||||
{
|
||||
item = out_of_band;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto row = index.row ();
|
||||
auto column = index.column ();
|
||||
|
||||
if (row < table_rows ())
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case Qt::ToolTipRole:
|
||||
case Qt::AccessibleDescriptionRole:
|
||||
switch (column)
|
||||
{
|
||||
case 0: item = tr ("Band name"); break;
|
||||
case 1: item = tr ("Lower frequency limit"); break;
|
||||
case 2: item = tr ("Upper frequency limit"); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SortRole:
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
switch (column)
|
||||
{
|
||||
case 0:
|
||||
if (SortRole == role)
|
||||
{
|
||||
// band name sorts by lower bound
|
||||
item = ADIF_bands[row].lower_bound_;
|
||||
}
|
||||
else
|
||||
{
|
||||
item = ADIF_bands[row].name_;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: item = ADIF_bands[row].lower_bound_; break;
|
||||
case 2: item = ADIF_bands[row].upper_bound_; break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::AccessibleTextRole:
|
||||
switch (column)
|
||||
{
|
||||
case 0: item = ADIF_bands[row].name_; break;
|
||||
case 1: item = ADIF_bands[row].lower_bound_; break;
|
||||
case 2: item = ADIF_bands[row].upper_bound_; break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::TextAlignmentRole:
|
||||
switch (column)
|
||||
{
|
||||
case 0:
|
||||
item = Qt::AlignHCenter + Qt::AlignVCenter;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
item = Qt::AlignRight + Qt::AlignVCenter;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
QVariant Bands::headerData (int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
QVariant result;
|
||||
|
||||
if (Qt::DisplayRole == role && Qt::Horizontal == orientation)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case 0: result = tr ("Band"); break;
|
||||
case 1: result = tr ("Lower Limit"); break;
|
||||
case 2: result = tr ("Upper Limit"); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = QAbstractTableModel::headerData (section, orientation, role);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#include "Bands.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <QString>
|
||||
#include <QVariant>
|
||||
|
||||
namespace
|
||||
{
|
||||
// Local structure to hold a single ADIF band definition.
|
||||
|
||||
// Table of ADIF band definitions as defined in the ADIF
|
||||
// specification.
|
||||
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},
|
||||
};
|
||||
|
||||
Bands::ADIFBand constexpr oob = {"OOB", 0, std::numeric_limits<Bands::Frequency>::max ()};
|
||||
|
||||
int constexpr table_rows ()
|
||||
{
|
||||
return sizeof (ADIF_bands) / sizeof (ADIF_bands[0]);
|
||||
}
|
||||
}
|
||||
|
||||
Bands::Bands (QObject * parent)
|
||||
: QAbstractTableModel {parent}
|
||||
{
|
||||
}
|
||||
|
||||
auto Bands::find (Frequency f) const -> ADIFBand const *
|
||||
{
|
||||
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 row_iter;
|
||||
}
|
||||
return &oob;
|
||||
}
|
||||
|
||||
auto Bands::out_of_band () const -> ADIFBand const *
|
||||
{
|
||||
return &oob;
|
||||
}
|
||||
|
||||
int Bands::rowCount (QModelIndex const& parent) const
|
||||
{
|
||||
return parent.isValid () ? 0 : table_rows ();
|
||||
}
|
||||
|
||||
int Bands::columnCount (QModelIndex const& parent) const
|
||||
{
|
||||
return parent.isValid () ? 0 : 3;
|
||||
}
|
||||
|
||||
Qt::ItemFlags Bands::flags (QModelIndex const& index) const
|
||||
{
|
||||
return QAbstractTableModel::flags (index) | Qt::ItemIsDropEnabled;
|
||||
}
|
||||
|
||||
QVariant Bands::data (QModelIndex const& index, int role) const
|
||||
{
|
||||
QVariant item;
|
||||
|
||||
if (!index.isValid ())
|
||||
{
|
||||
// Hijack root for OOB string.
|
||||
if (Qt::DisplayRole == role)
|
||||
{
|
||||
item = oob.name_;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto row = index.row ();
|
||||
auto column = index.column ();
|
||||
|
||||
if (row < table_rows ())
|
||||
{
|
||||
switch (role)
|
||||
{
|
||||
case Qt::ToolTipRole:
|
||||
case Qt::AccessibleDescriptionRole:
|
||||
switch (column)
|
||||
{
|
||||
case 0: item = tr ("Band name"); break;
|
||||
case 1: item = tr ("Lower frequency limit"); break;
|
||||
case 2: item = tr ("Upper frequency limit"); break;
|
||||
}
|
||||
break;
|
||||
|
||||
case SortRole:
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
switch (column)
|
||||
{
|
||||
case 0:
|
||||
if (SortRole == role)
|
||||
{
|
||||
// band name sorts by lower bound
|
||||
item = ADIF_bands[row].lower_bound_;
|
||||
}
|
||||
else
|
||||
{
|
||||
item = ADIF_bands[row].name_;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: item = ADIF_bands[row].lower_bound_; break;
|
||||
case 2: item = ADIF_bands[row].upper_bound_; break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::AccessibleTextRole:
|
||||
switch (column)
|
||||
{
|
||||
case 0: item = ADIF_bands[row].name_; break;
|
||||
case 1: item = ADIF_bands[row].lower_bound_; break;
|
||||
case 2: item = ADIF_bands[row].upper_bound_; break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::TextAlignmentRole:
|
||||
switch (column)
|
||||
{
|
||||
case 0:
|
||||
item = Qt::AlignHCenter + Qt::AlignVCenter;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
item = Qt::AlignRight + Qt::AlignVCenter;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
QVariant Bands::headerData (int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
QVariant result;
|
||||
|
||||
if (Qt::DisplayRole == role && Qt::Horizontal == orientation)
|
||||
{
|
||||
switch (section)
|
||||
{
|
||||
case 0: result = tr ("Band"); break;
|
||||
case 1: result = tr ("Lower Limit"); break;
|
||||
case 2: result = tr ("Upper Limit"); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = QAbstractTableModel::headerData (section, orientation, role);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
126
Bands.hpp
126
Bands.hpp
@ -1,58 +1,68 @@
|
||||
#ifndef BANDS_HPP__
|
||||
#define BANDS_HPP__
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
#include "Radio.hpp"
|
||||
|
||||
//
|
||||
// Class Bands
|
||||
//
|
||||
// Encapsulates information about amateur radio bands as defined by
|
||||
// the ADIF specification. The model is immutable. The rows are
|
||||
// stored in asscending order of frequency.
|
||||
//
|
||||
// Responsibilities
|
||||
//
|
||||
// Provides a well known band name mapped to lower and upper
|
||||
// frequency limits. Also provides a convenience operation to
|
||||
// determine the band details for any given frequency, the result of
|
||||
// which may be invalid if the given frequency doesn't lie within a
|
||||
// recognised band.
|
||||
//
|
||||
// Collaborations
|
||||
//
|
||||
// Implements the QAbstractTableModel interface as an immutable table
|
||||
// where rows are bands and columns are band name, lower frequency
|
||||
// limit and, upper ferquency limit respectively.
|
||||
//
|
||||
class Bands final
|
||||
: public QAbstractTableModel
|
||||
{
|
||||
public:
|
||||
explicit Bands (QObject * parent = nullptr);
|
||||
|
||||
//
|
||||
// Model API
|
||||
//
|
||||
QModelIndex find (QVariant const&) const; // find band Frequency is in
|
||||
|
||||
// Custom role for sorting.
|
||||
static int constexpr SortRole = Qt::UserRole;
|
||||
|
||||
// Implement the QAbstractTableModel interface
|
||||
int rowCount (QModelIndex const& parent = QModelIndex {}) const override;
|
||||
int columnCount (QModelIndex const& parent = QModelIndex {}) const override;
|
||||
Qt::ItemFlags flags (QModelIndex const& = QModelIndex {}) const override;
|
||||
QVariant headerData (int section, Qt::Orientation, int = Qt::DisplayRole) const override;
|
||||
|
||||
// The value return for the Qt::DisplayRole role for the root of the
|
||||
// model (invalid index) is a special string representing out of
|
||||
// band.
|
||||
//
|
||||
// All columns return a number for the custom role SortRole, this
|
||||
// number defines a strict frequency order for the rows.
|
||||
QVariant data (QModelIndex const&, int role = Qt::DisplayRole) const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
#ifndef BANDS_HPP__
|
||||
#define BANDS_HPP__
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
#include "Radio.hpp"
|
||||
|
||||
//
|
||||
// Class Bands
|
||||
//
|
||||
// Encapsulates information about amateur radio bands as defined by
|
||||
// the ADIF specification. The model is immutable. The rows are
|
||||
// stored in asscending order of frequency.
|
||||
//
|
||||
// Responsibilities
|
||||
//
|
||||
// Provides a well known band name mapped to lower and upper
|
||||
// frequency limits. Also provides a convenience operation to
|
||||
// determine the band details for any given frequency, the result of
|
||||
// which may be invalid if the given frequency doesn't lie within a
|
||||
// recognised band.
|
||||
//
|
||||
// Collaborations
|
||||
//
|
||||
// Implements the QAbstractTableModel interface as an immutable table
|
||||
// where rows are bands and columns are band name, lower frequency
|
||||
// limit and, upper ferquency limit respectively.
|
||||
//
|
||||
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
|
||||
//
|
||||
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;
|
||||
|
||||
// Implement the QAbstractTableModel interface
|
||||
int rowCount (QModelIndex const& parent = QModelIndex {}) const override;
|
||||
int columnCount (QModelIndex const& parent = QModelIndex {}) const override;
|
||||
Qt::ItemFlags flags (QModelIndex const& = QModelIndex {}) const override;
|
||||
QVariant headerData (int section, Qt::Orientation, int = Qt::DisplayRole) const override;
|
||||
|
||||
// The value return for the Qt::DisplayRole role for the root of the
|
||||
// model (invalid index) is a special string representing out of
|
||||
// band.
|
||||
//
|
||||
// All columns return a number for the custom role SortRole, this
|
||||
// number defines a strict frequency order for the rows.
|
||||
QVariant data (QModelIndex const&, int role = Qt::DisplayRole) const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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 ();
|
||||
@ -469,8 +464,9 @@ private:
|
||||
QStringListModel macros_;
|
||||
RearrangableMacrosModel next_macros_;
|
||||
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
|
||||
|
@ -1,53 +1,45 @@
|
||||
#ifndef FREQUENCY_ITEM_DELEGATE_HPP_
|
||||
#define FREQUENCY_ITEM_DELEGATE_HPP_
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class Bands;
|
||||
|
||||
//
|
||||
// Class FrequencyItemDelegate
|
||||
//
|
||||
// Item delegate for displaying and editing a Frequency item in a
|
||||
// view that uses a FrequencyLineEdit as an item delegate for the
|
||||
// edit role.
|
||||
//
|
||||
class FrequencyItemDelegate final
|
||||
: public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
explicit FrequencyItemDelegate (Bands const * bands, 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_;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Class FrequencyDeltaItemDelegate
|
||||
//
|
||||
// Item delegate for displaying and editing a FrequencyDelta item
|
||||
// in a view that uses a FrequencyDeltaLineEdit as an item
|
||||
// delegate for the edit role.
|
||||
//
|
||||
class FrequencyDeltaItemDelegate final
|
||||
: public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
explicit FrequencyDeltaItemDelegate (QObject * parent = nullptr)
|
||||
: QStyledItemDelegate {parent}
|
||||
{
|
||||
}
|
||||
|
||||
QString displayText (QVariant const& value, QLocale const&) const override;
|
||||
QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
#ifndef FREQUENCY_ITEM_DELEGATE_HPP_
|
||||
#define FREQUENCY_ITEM_DELEGATE_HPP_
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
//
|
||||
// Class FrequencyItemDelegate
|
||||
//
|
||||
// Item delegate for displaying and editing a Frequency item in a
|
||||
// view that uses a FrequencyLineEdit as an item delegate for the
|
||||
// edit role.
|
||||
//
|
||||
class FrequencyItemDelegate final
|
||||
: public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
explicit FrequencyItemDelegate (QObject * parent = nullptr)
|
||||
: QStyledItemDelegate {parent}
|
||||
{
|
||||
}
|
||||
|
||||
QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Class FrequencyDeltaItemDelegate
|
||||
//
|
||||
// Item delegate for displaying and editing a FrequencyDelta item
|
||||
// in a view that uses a FrequencyDeltaLineEdit as an item
|
||||
// delegate for the edit role.
|
||||
//
|
||||
class FrequencyDeltaItemDelegate final
|
||||
: public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
explicit FrequencyDeltaItemDelegate (QObject * parent = nullptr)
|
||||
: QStyledItemDelegate {parent}
|
||||
{
|
||||
}
|
||||
|
||||
QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -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
|
||||
|
@ -1,92 +1,87 @@
|
||||
#include "LiveFrequencyValidator.hpp"
|
||||
|
||||
#include <QLocale>
|
||||
#include <QString>
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "Bands.hpp"
|
||||
#include "FrequencyList.hpp"
|
||||
|
||||
#include "moc_LiveFrequencyValidator.cpp"
|
||||
|
||||
LiveFrequencyValidator::LiveFrequencyValidator (QComboBox * combo_box
|
||||
, Bands const * bands
|
||||
, 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
|
||||
}
|
||||
, bands_ {bands}
|
||||
, frequencies_ {frequencies}
|
||||
, combo_box_ {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;
|
||||
}
|
||||
|
||||
void LiveFrequencyValidator::fixup (QString& input) const
|
||||
{
|
||||
QRegExpValidator::fixup (input);
|
||||
|
||||
auto out_of_band = bands_->data (QModelIndex {}).toString ();
|
||||
|
||||
if (!out_of_band.startsWith (input))
|
||||
{
|
||||
if (input.contains ('m', Qt::CaseInsensitive))
|
||||
{
|
||||
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 {};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// frequency input
|
||||
auto f = Radio::frequency (input, 6);
|
||||
input = bands_->data (bands_->find (f)).toString ();
|
||||
Q_EMIT valid (f);
|
||||
}
|
||||
|
||||
if (out_of_band == input)
|
||||
{
|
||||
combo_box_->lineEdit ()->setStyleSheet ("QLineEdit {color: yellow; background-color : red;}");
|
||||
}
|
||||
else
|
||||
{
|
||||
combo_box_->lineEdit ()->setStyleSheet ({});
|
||||
}
|
||||
combo_box_->setCurrentText (input);
|
||||
}
|
||||
}
|
||||
#include "LiveFrequencyValidator.hpp"
|
||||
|
||||
#include <QLocale>
|
||||
#include <QString>
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "Bands.hpp"
|
||||
#include "FrequencyList.hpp"
|
||||
|
||||
#include "moc_LiveFrequencyValidator.cpp"
|
||||
|
||||
LiveFrequencyValidator::LiveFrequencyValidator (QComboBox * combo_box
|
||||
, Bands const * bands
|
||||
, 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}(\)"} // 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}
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void LiveFrequencyValidator::fixup (QString& input) const
|
||||
{
|
||||
QRegExpValidator::fixup (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 ();
|
||||
|
||||
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_->find (f)->name_;
|
||||
Q_EMIT valid (f);
|
||||
}
|
||||
|
||||
if (bands_->out_of_band ()->name_ == input)
|
||||
{
|
||||
combo_box_->lineEdit ()->setStyleSheet ("QLineEdit {color: yellow; background-color : red;}");
|
||||
}
|
||||
else
|
||||
{
|
||||
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…
Reference in New Issue
Block a user