mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2026-06-11 10:18:50 -04: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:
+250
-78
@@ -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 ()};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user