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:
Bill Somerville 2015-05-28 23:22:17 +00:00
parent e674ac4cb0
commit f200506571
30 changed files with 1319 additions and 940 deletions

View File

@ -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;

View File

@ -8,16 +8,10 @@
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[] = {
Bands::ADIFBand constexpr ADIF_bands[] = {
{"2190m", 136000u, 137000u},
{"630m", 472000u, 479000u},
{"560m", 501000u, 504000u},
@ -50,7 +44,7 @@ namespace
{"1mm", 241000000000u,250000000000u},
};
auto constexpr out_of_band = "OOB";
Bands::ADIFBand constexpr oob = {"OOB", 0, std::numeric_limits<Bands::Frequency>::max ()};
int constexpr table_rows ()
{
@ -63,19 +57,22 @@ Bands::Bands (QObject * parent)
{
}
QModelIndex Bands::find (QVariant const& v) const
auto Bands::find (Frequency f) const -> ADIFBand const *
{
auto f = v.value<Radio::Frequency> ();
auto end_iter = ADIF_bands + table_rows ();
auto row_iter = std::find_if (ADIF_bands, end_iter, [f] (ADIF_band const& band) {
auto const& end_iter = ADIF_bands + table_rows ();
auto const& row_iter = std::find_if (ADIF_bands, end_iter, [f] (ADIFBand const& band) {
return band.lower_bound_ <= f && f <= band.upper_bound_;
});
if (row_iter != end_iter)
{
return index (row_iter - ADIF_bands, 0); // return the band row index
return row_iter;
}
return &oob;
}
return QModelIndex {};
auto Bands::out_of_band () const -> ADIFBand const *
{
return &oob;
}
int Bands::rowCount (QModelIndex const& parent) const
@ -102,7 +99,7 @@ QVariant Bands::data (QModelIndex const& index, int role) const
// Hijack root for OOB string.
if (Qt::DisplayRole == role)
{
item = out_of_band;
item = oob.name_;
}
}
else

View File

@ -30,12 +30,22 @@ class Bands final
: public QAbstractTableModel
{
public:
using Frequency = Radio::Frequency;
struct ADIFBand
{
char const * const name_;
Radio::Frequency lower_bound_;
Radio::Frequency upper_bound_;
};
explicit Bands (QObject * parent = nullptr);
//
// Model API
//
QModelIndex find (QVariant const&) const; // find band Frequency is in
ADIFBand const * find (Frequency) const; // find band Frequency is in
ADIFBand const * out_of_band () const;
// Custom role for sorting.
static int constexpr SortRole = Qt::UserRole;

View File

@ -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

View File

@ -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);
}
@ -46,6 +57,8 @@ CandidateKeyFilter::~CandidateKeyFilter ()
}
void CandidateKeyFilter::set_active_key (QModelIndex const& index)
{
if (m_->referencing_)
{
if (index.isValid () )
{
@ -54,9 +67,15 @@ void CandidateKeyFilter::set_active_key (QModelIndex const& index)
}
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.

View File

@ -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

View File

@ -171,6 +171,7 @@
#include "TransceiverFactory.hpp"
#include "Transceiver.hpp"
#include "Bands.hpp"
#include "Modes.hpp"
#include "FrequencyList.hpp"
#include "StationList.hpp"
#include "NetworkServerLookup.hpp"
@ -182,17 +183,6 @@
namespace
{
struct init
{
init ()
{
qRegisterMetaType<Configuration::DataMode> ("Configuration::DataMode");
qRegisterMetaTypeStreamOperators<Configuration::DataMode> ("Configuration::DataMode");
qRegisterMetaType<Configuration::Type2MsgGen> ("Configuration::Type2MsgGen");
qRegisterMetaTypeStreamOperators<Configuration::Type2MsgGen> ("Configuration::Type2MsgGen");
}
} static_initializer;
// these undocumented flag values when stored in (Qt::UserRole - 1)
// of a ComboBox item model index allow the item to be enabled or
// disabled
@ -210,14 +200,17 @@ class FrequencyDialog final
: public QDialog
{
public:
using Frequency = Radio::Frequency;
using Item = FrequencyList::Item;
explicit FrequencyDialog (QWidget * parent = nullptr)
explicit FrequencyDialog (Modes * modes_model, QWidget * parent = nullptr)
: QDialog {parent}
{
setWindowTitle (QApplication::applicationName () + " - " + tr ("Add Frequency"));
mode_combo_box_.setModel (modes_model);
auto form_layout = new QFormLayout ();
form_layout->addRow (tr ("&Mode:"), &mode_combo_box_);
form_layout->addRow (tr ("&Frequency (MHz):"), &frequency_line_edit_);
auto main_layout = new QVBoxLayout (this);
@ -230,12 +223,13 @@ public:
connect (button_box, &QDialogButtonBox::rejected, this, &FrequencyDialog::reject);
}
Frequency frequency () const
Item item () const
{
return frequency_line_edit_.frequency ();
return {frequency_line_edit_.frequency (), Modes::value (mode_combo_box_.currentText ())};
}
private:
QComboBox mode_combo_box_;
FrequencyLineEdit frequency_line_edit_;
};
@ -249,7 +243,7 @@ class StationDialog final
public:
explicit StationDialog (StationList const * stations, Bands * bands, QWidget * parent = nullptr)
: QDialog {parent}
, filtered_bands_ {new CandidateKeyFilter {stations, bands}}
, filtered_bands_ {new CandidateKeyFilter {bands, stations, 0, 0}}
{
setWindowTitle (QApplication::applicationName () + " - " + tr ("Add Station"));
@ -311,6 +305,7 @@ public:
};
//
// Class MessageItemDelegate
//
// Item delegate for message entry such as free text message macros.
@ -336,7 +331,6 @@ public:
}
};
// Internal implementation of the Configuration class.
class Configuration::impl final
: public QDialog
@ -416,6 +410,7 @@ private:
void delete_selected_macros (QModelIndexList);
Q_SLOT void on_save_path_select_push_button_clicked (bool);
Q_SLOT void delete_frequencies ();
Q_SLOT void on_reset_frequencies_push_button_clicked (bool);
Q_SLOT void insert_frequency ();
Q_SLOT void delete_stations ();
Q_SLOT void insert_station ();
@ -471,6 +466,7 @@ private:
QAction * macro_delete_action_;
Bands bands_;
Modes modes_;
FrequencyList frequencies_;
FrequencyList next_frequencies_;
StationList stations_;
@ -697,24 +693,17 @@ void Configuration::sync_transceiver (bool force_signal, bool enforce_mode_and_s
m_->sync_transceiver (force_signal);
}
Configuration::impl::impl (Configuration * self, QSettings * settings, QWidget * parent)
: QDialog {parent}
, self_ {self}
, ui_ {new Ui::configuration_dialog}
, settings_ {settings}
, doc_dir_ {QApplication::applicationDirPath ()}
, frequencies_ {
{ 136000, 136130, 474200, 1836600, 1838000, 3576000, 3592600, 5287200, 5357000,
7038600, 7076000, 10138000, 10138700, 14076000, 14095600, 18102000, 18104600,
21076000, 21094600, 24917000, 24924600, 28076000, 28124600, 50276000, 50293000,
70091000, 144000000, 144489000, 222000000, 432000000, 432300000,
902000000, 1296000000, 1296500000, 2301000000, 2304000000, 2320000000, 3400000000,
3456000000, 5760000000,10368000000, 24048000000 }
}
, frequencies_ {&bands_}
, next_frequencies_ {&bands_}
, stations_ {&bands_}
, next_stations_ {&bands_}
, frequency_dialog_ {new FrequencyDialog {this}}
, frequency_dialog_ {new FrequencyDialog {&modes_, this}}
, station_dialog_ {new StationDialog {&next_stations_, &bands_, this}}
, rig_active_ {false}
, have_rig_ {false}
@ -891,12 +880,12 @@ Configuration::impl::impl (Configuration * self, QSettings * settings, QWidget *
//
// setup working frequencies table model & view
//
frequencies_.sort (0);
frequencies_.sort (FrequencyList::frequency_column);
ui_->frequencies_table_view->setModel (&next_frequencies_);
ui_->frequencies_table_view->sortByColumn (0, Qt::AscendingOrder);
ui_->frequencies_table_view->setItemDelegateForColumn (0, new FrequencyItemDelegate {&bands_, this});
ui_->frequencies_table_view->setColumnHidden (1, true);
ui_->frequencies_table_view->sortByColumn (FrequencyList::frequency_column, Qt::AscendingOrder);
ui_->frequencies_table_view->setItemDelegateForColumn (FrequencyList::mode_column, new ForeignKeyDelegate {&modes_, 0, this});
ui_->frequencies_table_view->setColumnHidden (FrequencyList::frequency_mhz_column, true);
frequency_delete_action_ = new QAction {tr ("&Delete"), ui_->frequencies_table_view};
ui_->frequencies_table_view->insertAction (nullptr, frequency_delete_action_);
@ -910,13 +899,11 @@ Configuration::impl::impl (Configuration * self, QSettings * settings, QWidget *
//
// setup stations table model & view
//
stations_.sort (0);
stations_.sort (StationList::band_column);
ui_->stations_table_view->setModel (&next_stations_);
ui_->stations_table_view->sortByColumn (0, Qt::AscendingOrder);
ui_->stations_table_view->setColumnWidth (1, 150);
ui_->stations_table_view->setItemDelegateForColumn (0, new ForeignKeyDelegate {&next_stations_, &bands_, 0, 0, this});
ui_->stations_table_view->setItemDelegateForColumn (1, new FrequencyDeltaItemDelegate {this});
ui_->stations_table_view->sortByColumn (StationList::band_column, Qt::AscendingOrder);
ui_->stations_table_view->setItemDelegateForColumn (StationList::band_column, new ForeignKeyDelegate {&bands_, &next_stations_, 0, StationList::band_column, this});
station_delete_action_ = new QAction {tr ("&Delete"), ui_->stations_table_view};
ui_->stations_table_view->insertAction (nullptr, station_delete_action_);
@ -1041,8 +1028,8 @@ void Configuration::impl::initialize_models ()
}
next_macros_.setStringList (macros_.stringList ());
next_frequencies_ = frequencies_.frequencies ();
next_stations_ = stations_.stations ();
next_frequencies_.frequency_list (frequencies_.frequency_list ());
next_stations_.station_list (stations_.station_list ());
set_rig_invariants ();
}
@ -1170,10 +1157,10 @@ void Configuration::impl::read_settings ()
if (settings_->contains ("frequencies"))
{
frequencies_ = settings_->value ("frequencies").value<Radio::Frequencies> ();
frequencies_.frequency_list (settings_->value ("frequencies").value<FrequencyList::FrequencyItems> ());
}
stations_ = settings_->value ("stations").value<StationList::Stations> ();
stations_.station_list (settings_->value ("stations").value<StationList::Stations> ());
log_as_RTTY_ = settings_->value ("toRTTY", false).toBool ();
report_in_comments_ = settings_->value("dBtoComments", false).toBool ();
@ -1262,8 +1249,8 @@ void Configuration::impl::write_settings ()
settings_->setValue ("After73", id_after_73_);
settings_->setValue ("TxQSYAllowed", tx_QSY_allowed_);
settings_->setValue ("Macros", macros_.stringList ());
settings_->setValue ("frequencies", QVariant::fromValue (frequencies_.frequencies ()));
settings_->setValue ("stations", QVariant::fromValue (stations_.stations ()));
settings_->setValue ("frequencies", QVariant::fromValue (frequencies_.frequency_list ()));
settings_->setValue ("stations", QVariant::fromValue (stations_.station_list ()));
settings_->setValue ("toRTTY", log_as_RTTY_);
settings_->setValue ("dBtoComments", report_in_comments_);
settings_->setValue ("Rig", rig_params_.rig_name);
@ -1674,16 +1661,16 @@ void Configuration::impl::accept ()
macros_.setStringList (next_macros_.stringList ());
}
if (frequencies_.frequencies () != next_frequencies_.frequencies ())
if (frequencies_.frequency_list () != next_frequencies_.frequency_list ())
{
frequencies_ = next_frequencies_.frequencies ();
frequencies_.sort (0);
frequencies_.frequency_list (next_frequencies_.frequency_list ());
frequencies_.sort (FrequencyList::frequency_column);
}
if (stations_.stations () != next_stations_.stations ())
if (stations_.station_list () != next_stations_.station_list ())
{
stations_ = next_stations_.stations ();
stations_.sort (0);
stations_.station_list(next_stations_.station_list ());
stations_.sort (StationList::band_column);
}
write_settings (); // make visible to all
@ -1975,13 +1962,26 @@ void Configuration::impl::delete_frequencies ()
auto selection_model = ui_->frequencies_table_view->selectionModel ();
selection_model->select (selection_model->selection (), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
next_frequencies_.removeDisjointRows (selection_model->selectedRows ());
ui_->frequencies_table_view->resizeColumnToContents (FrequencyList::mode_column);
}
void Configuration::impl::on_reset_frequencies_push_button_clicked (bool /* checked */)
{
if (QMessageBox::Yes == QMessageBox::question (this, tr ("Reset Working Frequencies")
, tr ("Are you sure you want to discard your current "
"working frequencies and replace them with default "
"ones?")))
{
next_frequencies_.reset_to_defaults ();
}
}
void Configuration::impl::insert_frequency ()
{
if (QDialog::Accepted == frequency_dialog_->exec ())
{
ui_->frequencies_table_view->setCurrentIndex (next_frequencies_.add (frequency_dialog_->frequency ()));
ui_->frequencies_table_view->setCurrentIndex (next_frequencies_.add (frequency_dialog_->item ()));
ui_->frequencies_table_view->resizeColumnToContents (FrequencyList::mode_column);
}
}
@ -1990,6 +1990,8 @@ void Configuration::impl::delete_stations ()
auto selection_model = ui_->stations_table_view->selectionModel ();
selection_model->select (selection_model->selection (), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows);
next_stations_.removeDisjointRows (selection_model->selectedRows ());
ui_->stations_table_view->resizeColumnToContents (StationList::band_column);
ui_->stations_table_view->resizeColumnToContents (StationList::offset_column);
}
void Configuration::impl::insert_station ()
@ -1997,6 +1999,8 @@ void Configuration::impl::insert_station ()
if (QDialog::Accepted == station_dialog_->exec ())
{
ui_->stations_table_view->setCurrentIndex (next_stations_.add (station_dialog_->station ()));
ui_->stations_table_view->resizeColumnToContents (StationList::band_column);
ui_->stations_table_view->resizeColumnToContents (StationList::offset_column);
}
}

View File

@ -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,7 +1842,33 @@ for assessing propagation and system performance.</string>
</attribute>
</widget>
</item>
<item row="0" column="2">
<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>
@ -1918,20 +1950,7 @@ for assessing propagation and system performance.</string>
</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">
<item>
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -1945,6 +1964,8 @@ for assessing propagation and system performance.</string>
</spacer>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
@ -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>

View File

@ -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}}
{
}

View File

@ -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;

View File

@ -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

View File

@ -3,8 +3,6 @@
#include <QStyledItemDelegate>
class Bands;
//
// Class FrequencyItemDelegate
//
@ -16,17 +14,12 @@ class FrequencyItemDelegate final
: public QStyledItemDelegate
{
public:
explicit FrequencyItemDelegate (Bands const * bands, QObject * parent = nullptr)
explicit FrequencyItemDelegate (QObject * parent = nullptr)
: QStyledItemDelegate {parent}
, bands_ {bands}
{
}
QString displayText (QVariant const& value, QLocale const&) const override;
QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
private:
Bands const * bands_;
};
@ -46,7 +39,6 @@ public:
{
}
QString displayText (QVariant const& value, QLocale const&) const override;
QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
};

View File

@ -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,22 +409,45 @@ 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 ())
{
QVector<int> roles;
roles << role;
auto& item = frequency_list_[row];
switch (model_index.column ())
{
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> ();
auto original_frequency = frequencies_.at (row);
if (frequency != original_frequency)
if (frequency != item.frequency_)
{
frequencies_.replace (row, frequency);
Q_EMIT dataChanged (model_index, index (model_index.row (), 1), QVector<int> {} << role);
}
item.frequency_ = frequency;
// mark derived column (1) changed as well
Q_EMIT dataChanged (index (model_index.row (), 1), model_index, roles);
changed = true;
}
}
break;
}
}
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 ()};
}

View File

@ -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

View File

@ -17,7 +17,7 @@ LiveFrequencyValidator::LiveFrequencyValidator (QComboBox * combo_box
: QRegExpValidator {
QRegExp { // frequency in MHz or band
bands->data (QModelIndex {}).toString () // out of band string
+ QString {R"(|((\d{0,6}(\)"} // up to 6 digits
+ 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
@ -34,7 +34,6 @@ LiveFrequencyValidator::LiveFrequencyValidator (QComboBox * combo_box
auto LiveFrequencyValidator::validate (QString& input, int& pos) const -> State
{
auto state = QRegExpValidator::validate (input, pos);
// by never being Acceptable we force fixup calls on ENTER or
// losing focus
return Acceptable == state ? Intermediate : state;
@ -43,23 +42,19 @@ auto LiveFrequencyValidator::validate (QString& input, int& pos) const -> State
void LiveFrequencyValidator::fixup (QString& input) const
{
QRegExpValidator::fixup (input);
auto out_of_band = bands_->data (QModelIndex {}).toString ();
if (!out_of_band.startsWith (input))
auto const& out_of_band = bands_->out_of_band ();
if (!QString {out_of_band->name_}.startsWith (input))
{
if (input.contains ('m', Qt::CaseInsensitive))
{
input = input.toLower ();
QVector<QVariant> frequencies;
for (int r = 0; r < frequencies_->rowCount (); ++r)
Q_FOREACH (auto const& item, frequencies_->frequency_list ())
{
auto frequency = frequencies_->index (r, 0).data ();
auto band_index = bands_->find (frequency);
if (band_index.data ().toString () == input)
if (bands_->find (item.frequency_)->name_ == input)
{
frequencies << frequency;
frequencies << item.frequency_;
}
}
if (!frequencies.isEmpty ())
@ -75,11 +70,11 @@ void LiveFrequencyValidator::fixup (QString& input) const
{
// frequency input
auto f = Radio::frequency (input, 6);
input = bands_->data (bands_->find (f)).toString ();
input = bands_->find (f)->name_;
Q_EMIT valid (f);
}
if (out_of_band == input)
if (bands_->out_of_band ()->name_ == input)
{
combo_box_->lineEdit ()->setStyleSheet ("QLineEdit {color: yellow; background-color : red;}");
}

72
MetaDataRegistry.cpp Normal file
View 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
View File

@ -0,0 +1,6 @@
#ifndef META_DATA_REGISTRY_HPP__
#define META_DATA_REGISTRY_HPP__
void register_types ();
#endif

92
Modes.cpp Normal file
View 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
View 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

View File

@ -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};

View File

@ -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

View File

@ -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,21 +202,18 @@ 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
}
@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;
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,11 +1648,12 @@ void MainWindow::readFromStdout() //readFromStdout
msgBox("Cannot open \"" + f.fileName () + "\" for append:" + f.errorString ());
}
if (m_config.insert_blank () && m_blankLine) {
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 ();
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;
@ -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 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_;
}
auto f = frequency.value<Frequency> ();
if (m_plus2kHz) f += 2000;
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;

View File

@ -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();
};

View File

@ -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">