mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-22 04:11:16 -05:00
Merge branch 'release-2.1.0' of bitbucket.org:k1jt/wsjtx into release-2.1.0
This commit is contained in:
commit
4b51f423c2
@ -237,6 +237,7 @@ set (wsjt_qt_CXXSRCS
|
||||
models/FrequencyList.cpp
|
||||
models/StationList.cpp
|
||||
widgets/FrequencyLineEdit.cpp
|
||||
widgets/FrequencyDeltaLineEdit.cpp
|
||||
item_delegates/CandidateKeyFilter.cpp
|
||||
item_delegates/ForeignKeyDelegate.cpp
|
||||
validators/LiveFrequencyValidator.cpp
|
||||
@ -279,9 +280,12 @@ set (wsjt_qt_CXXSRCS
|
||||
widgets/CabrilloLogWindow.cpp
|
||||
item_delegates/CallsignDelegate.cpp
|
||||
item_delegates/MaidenheadLocatorDelegate.cpp
|
||||
item_delegates/FrequencyDelegate.cpp
|
||||
item_delegates/FrequencyDeltaDelegate.cpp
|
||||
models/CabrilloLog.cpp
|
||||
logbook/AD1CCty.cpp
|
||||
logbook/WorkedBefore.cpp
|
||||
logbook/Multiplier.cpp
|
||||
)
|
||||
|
||||
set (wsjt_qtmm_CXXSRCS
|
||||
|
@ -167,8 +167,11 @@
|
||||
#include "MetaDataRegistry.hpp"
|
||||
#include "SettingsGroup.hpp"
|
||||
#include "widgets/FrequencyLineEdit.hpp"
|
||||
#include "widgets/FrequencyDeltaLineEdit.hpp"
|
||||
#include "item_delegates/CandidateKeyFilter.hpp"
|
||||
#include "item_delegates/ForeignKeyDelegate.hpp"
|
||||
#include "item_delegates/FrequencyDelegate.hpp"
|
||||
#include "item_delegates/FrequencyDeltaDelegate.hpp"
|
||||
#include "TransceiverFactory.hpp"
|
||||
#include "Transceiver.hpp"
|
||||
#include "models/Bands.hpp"
|
||||
@ -564,6 +567,7 @@ private:
|
||||
DecodeHighlightingModel decode_highlighing_model_;
|
||||
DecodeHighlightingModel next_decode_highlighing_model_;
|
||||
bool highlight_by_mode_;
|
||||
bool include_WAE_entities_;
|
||||
int LotW_days_since_upload_;
|
||||
|
||||
TransceiverFactory::ParameterPack rig_params_;
|
||||
@ -745,6 +749,7 @@ bool Configuration::pwrBandTuneMemory () const {return m_->pwrBandTuneMemory_;}
|
||||
LotWUsers const& Configuration::lotw_users () const {return m_->lotw_users_;}
|
||||
DecodeHighlightingModel const& Configuration::decode_highlighting () const {return m_->decode_highlighing_model_;}
|
||||
bool Configuration::highlight_by_mode () const {return m_->highlight_by_mode_;}
|
||||
bool Configuration::include_WAE_entities () const {return m_->include_WAE_entities_;}
|
||||
|
||||
void Configuration::set_calibration (CalibrationParams params)
|
||||
{
|
||||
@ -950,6 +955,7 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
|
||||
, station_insert_action_ {tr ("&Insert ..."), nullptr}
|
||||
, station_dialog_ {new StationDialog {&next_stations_, &bands_, this}}
|
||||
, highlight_by_mode_ {false}
|
||||
, include_WAE_entities_ {false}
|
||||
, LotW_days_since_upload_ {0}
|
||||
, last_port_type_ {TransceiverFactory::Capabilities::none}
|
||||
, rig_is_dummy_ {false}
|
||||
@ -1119,9 +1125,7 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
|
||||
ui_->frequencies_table_view->setColumnHidden (FrequencyList_v2::frequency_mhz_column, true);
|
||||
|
||||
// delegates
|
||||
auto frequencies_item_delegate = new QStyledItemDelegate {this};
|
||||
frequencies_item_delegate->setItemEditorFactory (item_editor_factory ());
|
||||
ui_->frequencies_table_view->setItemDelegate (frequencies_item_delegate);
|
||||
ui_->frequencies_table_view->setItemDelegateForColumn (FrequencyList_v2::frequency_column, new FrequencyDelegate {this});
|
||||
ui_->frequencies_table_view->setItemDelegateForColumn (FrequencyList_v2::region_column, new ForeignKeyDelegate {®ions_, 0, this});
|
||||
ui_->frequencies_table_view->setItemDelegateForColumn (FrequencyList_v2::mode_column, new ForeignKeyDelegate {&modes_, 0, this});
|
||||
|
||||
@ -1160,9 +1164,7 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network
|
||||
ui_->stations_table_view->sortByColumn (StationList::band_column, Qt::AscendingOrder);
|
||||
|
||||
// stations delegates
|
||||
auto stations_item_delegate = new QStyledItemDelegate {this};
|
||||
stations_item_delegate->setItemEditorFactory (item_editor_factory ());
|
||||
ui_->stations_table_view->setItemDelegate (stations_item_delegate);
|
||||
ui_->stations_table_view->setItemDelegateForColumn (StationList::offset_column, new FrequencyDeltaDelegate {this});
|
||||
ui_->stations_table_view->setItemDelegateForColumn (StationList::band_column, new ForeignKeyDelegate {&bands_, &next_stations_, 0, StationList::band_column, this});
|
||||
|
||||
// stations actions
|
||||
@ -1319,6 +1321,7 @@ void Configuration::impl::initialize_models ()
|
||||
|
||||
next_decode_highlighing_model_.items (decode_highlighing_model_.items ());
|
||||
ui_->highlight_by_mode_check_box->setChecked (highlight_by_mode_);
|
||||
ui_->include_WAE_check_box->setChecked (include_WAE_entities_);
|
||||
ui_->LotW_days_since_upload_spin_box->setValue (LotW_days_since_upload_);
|
||||
|
||||
set_rig_invariants ();
|
||||
@ -1467,6 +1470,7 @@ void Configuration::impl::read_settings ()
|
||||
if (!highlight_items.size ()) highlight_items = DecodeHighlightingModel::default_items ();
|
||||
decode_highlighing_model_.items (highlight_items);
|
||||
highlight_by_mode_ = settings_->value("HighlightByMode", false).toBool ();
|
||||
include_WAE_entities_ = settings_->value("IncludeWAEEntities", false).toBool ();
|
||||
LotW_days_since_upload_ = settings_->value ("LotWDaysSinceLastUpload", 365).toInt ();
|
||||
lotw_users_.set_age_constraint (LotW_days_since_upload_);
|
||||
|
||||
@ -1579,7 +1583,7 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("FrequenciesForRegionModes", QVariant::fromValue (frequencies_.frequency_list ()));
|
||||
settings_->setValue ("stations", QVariant::fromValue (stations_.station_list ()));
|
||||
settings_->setValue ("DecodeHighlighting", QVariant::fromValue (decode_highlighing_model_.items ()));
|
||||
settings_->setValue ("HighlightByMode", highlight_by_mode_);
|
||||
settings_->setValue ("IncludeWAEEntities", include_WAE_entities_);
|
||||
settings_->setValue ("LotWDaysSinceLastUpload", LotW_days_since_upload_);
|
||||
settings_->setValue ("toRTTY", log_as_RTTY_);
|
||||
settings_->setValue ("dBtoComments", report_in_comments_);
|
||||
@ -2116,6 +2120,7 @@ void Configuration::impl::accept ()
|
||||
Q_EMIT self_->decode_highlighting_changed (decode_highlighing_model_);
|
||||
}
|
||||
highlight_by_mode_ = ui_->highlight_by_mode_check_box->isChecked ();
|
||||
include_WAE_entities_ = ui_->include_WAE_check_box->isChecked ();
|
||||
LotW_days_since_upload_ = ui_->LotW_days_since_upload_spin_box->value ();
|
||||
lotw_users_.set_age_constraint (LotW_days_since_upload_);
|
||||
|
||||
|
@ -177,6 +177,7 @@ public:
|
||||
LotWUsers const& lotw_users () const;
|
||||
DecodeHighlightingModel const& decode_highlighting () const;
|
||||
bool highlight_by_mode () const;
|
||||
bool include_WAE_entities () const;
|
||||
|
||||
enum class SpecialOperatingActivity {NONE, NA_VHF, EU_VHF, FIELD_DAY, RTTY, FOX, HOUND};
|
||||
SpecialOperatingActivity special_op_id () const;
|
||||
|
@ -2294,6 +2294,23 @@ Right click for insert and delete options.</string>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout_20">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="include_WAE_check_box"/>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="includeExtraWAEEntitiesLabel">
|
||||
<property name="text">
|
||||
<string>Include extra WAE entities</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>include_WAE_check_box</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -2306,35 +2323,6 @@ Right click for insert and delete options.</string>
|
||||
<string>Logbook of the World User Validation</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_18">
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Age of last upload less than:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>LotW_days_since_upload_spin_box</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="LotW_days_since_upload_spin_box">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Adjust this spin box to set the age threshold of LotW user's last upload date that is accepted as a current LotW user.</p></body></html></string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> days</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>365</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="text">
|
||||
@ -2369,6 +2357,35 @@ Right click for insert and delete options.</string>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_14">
|
||||
<property name="text">
|
||||
<string>Age of last upload less than:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>LotW_days_since_upload_spin_box</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="LotW_days_since_upload_spin_box">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Adjust this spin box to set the age threshold of LotW user's last upload date that is accepted as a current LotW user.</p></body></html></string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> days</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>365</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -3085,13 +3102,13 @@ Right click for insert and delete options.</string>
|
||||
</connection>
|
||||
</connections>
|
||||
<buttongroups>
|
||||
<buttongroup name="split_mode_button_group"/>
|
||||
<buttongroup name="special_op_activity_button_group"/>
|
||||
<buttongroup name="CAT_data_bits_button_group"/>
|
||||
<buttongroup name="CAT_handshake_button_group"/>
|
||||
<buttongroup name="TX_audio_source_button_group"/>
|
||||
<buttongroup name="split_mode_button_group"/>
|
||||
<buttongroup name="TX_mode_button_group"/>
|
||||
<buttongroup name="PTT_method_button_group"/>
|
||||
<buttongroup name="special_op_activity_button_group"/>
|
||||
<buttongroup name="CAT_stop_bits_button_group"/>
|
||||
<buttongroup name="CAT_handshake_button_group"/>
|
||||
<buttongroup name="TX_audio_source_button_group"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
@ -127,7 +127,7 @@ int DXLabSuiteCommanderTransceiver::do_start ()
|
||||
throw error {tr ("DX Lab Suite Commander didn't respond correctly reading frequency: ") + reply};
|
||||
}
|
||||
|
||||
poll ();
|
||||
do_poll ();
|
||||
return resolution;
|
||||
}
|
||||
|
||||
@ -247,7 +247,7 @@ void DXLabSuiteCommanderTransceiver::do_mode (MODE m)
|
||||
update_mode (m);
|
||||
}
|
||||
|
||||
void DXLabSuiteCommanderTransceiver::poll ()
|
||||
void DXLabSuiteCommanderTransceiver::do_poll ()
|
||||
{
|
||||
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
|
||||
bool quiet {false};
|
||||
|
@ -39,7 +39,7 @@ protected:
|
||||
void do_mode (MODE) override;
|
||||
void do_ptt (bool on) override;
|
||||
|
||||
void poll () override;
|
||||
void do_poll () override;
|
||||
|
||||
private:
|
||||
MODE get_mode (bool no_debug = false);
|
||||
|
@ -885,7 +885,7 @@ bool HRDTransceiver::is_button_checked (int button_index, bool no_debug)
|
||||
return "1" == reply;
|
||||
}
|
||||
|
||||
void HRDTransceiver::poll ()
|
||||
void HRDTransceiver::do_poll ()
|
||||
{
|
||||
#if WSJT_TRACE_CAT && WSJT_TRACE_CAT_POLLS
|
||||
bool quiet {false};
|
||||
|
@ -48,7 +48,7 @@ protected:
|
||||
void do_ptt (bool on) override;
|
||||
|
||||
// Implement the PollingTransceiver interface.
|
||||
void poll () override;
|
||||
void do_poll () override;
|
||||
|
||||
private:
|
||||
QString send_command (QString const&, bool no_debug = false, bool prepend_context = true, bool recurse = false);
|
||||
|
@ -632,7 +632,7 @@ int HamlibTransceiver::do_start ()
|
||||
resolution = -1; // best guess
|
||||
}
|
||||
|
||||
poll ();
|
||||
do_poll ();
|
||||
|
||||
TRACE_CAT ("HamlibTransceiver", "exit" << state () << "reversed =" << reversed_ << "resolution = " << resolution);
|
||||
return resolution;
|
||||
@ -898,7 +898,7 @@ void HamlibTransceiver::do_mode (MODE mode)
|
||||
update_mode (mode);
|
||||
}
|
||||
|
||||
void HamlibTransceiver::poll ()
|
||||
void HamlibTransceiver::do_poll ()
|
||||
{
|
||||
#if !WSJT_TRACE_CAT_POLLS
|
||||
#if defined (NDEBUG)
|
||||
|
@ -40,7 +40,7 @@ class HamlibTransceiver final
|
||||
void do_mode (MODE) override;
|
||||
void do_ptt (bool) override;
|
||||
|
||||
void poll () override;
|
||||
void do_poll () override;
|
||||
|
||||
void error_check (int ret_code, QString const& doing) const;
|
||||
void set_conf (char const * item, char const * value);
|
||||
|
@ -14,17 +14,35 @@
|
||||
#include "WFPalette.hpp"
|
||||
#include "models/IARURegions.hpp"
|
||||
#include "models/DecodeHighlightingModel.hpp"
|
||||
#include "widgets/FrequencyLineEdit.hpp"
|
||||
#include "widgets/DateTimeEdit.hpp"
|
||||
|
||||
QItemEditorFactory * item_editor_factory ()
|
||||
namespace
|
||||
{
|
||||
static QItemEditorFactory * our_item_editor_factory = new QItemEditorFactory;
|
||||
return our_item_editor_factory;
|
||||
class ItemEditorFactory final
|
||||
: public QItemEditorFactory
|
||||
{
|
||||
public:
|
||||
ItemEditorFactory ()
|
||||
: default_factory_ {QItemEditorFactory::defaultFactory ()}
|
||||
{
|
||||
}
|
||||
|
||||
QWidget * createEditor (int user_type, QWidget * parent) const override
|
||||
{
|
||||
auto editor = QItemEditorFactory::createEditor (user_type, parent);
|
||||
return editor ? editor : default_factory_->createEditor (user_type, parent);
|
||||
}
|
||||
|
||||
private:
|
||||
QItemEditorFactory const * default_factory_;
|
||||
};
|
||||
}
|
||||
|
||||
void register_types ()
|
||||
{
|
||||
auto item_editor_factory = new ItemEditorFactory;
|
||||
QItemEditorFactory::setDefaultFactory (item_editor_factory);
|
||||
|
||||
// types in Radio.hpp are registered in their own translation unit
|
||||
// as they are needed in the wsjtx_udp shared library too
|
||||
|
||||
@ -32,12 +50,7 @@ void register_types ()
|
||||
// used as signal/slot connection arguments since the new Qt 5.5
|
||||
// Q_ENUM macro only seems to register the unqualified name
|
||||
|
||||
item_editor_factory ()->registerEditor (qMetaTypeId<Radio::Frequency> (), new QStandardItemEditorCreator<FrequencyLineEdit> ());
|
||||
//auto frequency_delta_type_id = qRegisterMetaType<Radio::FrequencyDelta> ("FrequencyDelta");
|
||||
item_editor_factory ()->registerEditor (qMetaTypeId<Radio::FrequencyDelta> (), new QStandardItemEditorCreator<FrequencyDeltaLineEdit> ());
|
||||
auto factory = new QItemEditorFactory;
|
||||
factory->registerEditor (qMetaTypeId<QDateTime> (), new QStandardItemEditorCreator<DateTimeEdit> ());
|
||||
QItemEditorFactory::setDefaultFactory (factory);
|
||||
item_editor_factory->registerEditor (qMetaTypeId<QDateTime> (), new QStandardItemEditorCreator<DateTimeEdit> ());
|
||||
|
||||
// Frequency list model
|
||||
qRegisterMetaTypeStreamOperators<FrequencyList_v2::Item> ("Item_v2");
|
||||
|
@ -1,9 +1,6 @@
|
||||
#ifndef META_DATA_REGISTRY_HPP__
|
||||
#define META_DATA_REGISTRY_HPP__
|
||||
|
||||
class QItemEditorFactory;
|
||||
|
||||
QItemEditorFactory * item_editor_factory ();
|
||||
void register_types ();
|
||||
|
||||
#endif
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <QDebug>
|
||||
#include <objbase.h>
|
||||
#include <QThread>
|
||||
#include <QEventLoop>
|
||||
|
||||
#include "qt_helpers.hpP"
|
||||
|
||||
@ -109,6 +110,15 @@ OmniRigTransceiver::OmniRigTransceiver (std::unique_ptr<TransceiverBase> wrapped
|
||||
{
|
||||
}
|
||||
|
||||
// returns false on time out
|
||||
bool OmniRigTransceiver::await_notification_with_timeout (int timeout)
|
||||
{
|
||||
QEventLoop el;
|
||||
connect (this, &OmniRigTransceiver::notified, &el, [&el] () {el.exit (1);});
|
||||
QTimer::singleShot (timeout, Qt::CoarseTimer, &el, [&el] () {el.exit (0);});
|
||||
return 1 == el.exec (); // wait for notify or timer
|
||||
}
|
||||
|
||||
int OmniRigTransceiver::do_start ()
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "starting");
|
||||
@ -182,101 +192,97 @@ int OmniRigTransceiver::do_start ()
|
||||
.arg (readable_params_, 8, 16, QChar ('0'))
|
||||
.arg (writable_params_, 8, 16, QChar ('0'))
|
||||
.arg (rig_number_).toLocal8Bit ());
|
||||
|
||||
offline_timer_.reset (new QTimer);
|
||||
offline_timer_->setSingleShot (true);
|
||||
offline_timer_->setInterval (5 * 1000);
|
||||
connect (&*offline_timer_, &QTimer::timeout, this, &OmniRigTransceiver::timeout_check);
|
||||
|
||||
for (unsigned tries {0}; tries < 10; ++tries)
|
||||
if (OmniRig::ST_ONLINE != rig_->Status ())
|
||||
{
|
||||
QThread::msleep (100); // wait until OmniRig polls the rig
|
||||
auto f = rig_->GetRxFrequency ();
|
||||
int resolution {0};
|
||||
if (f)
|
||||
throw_qstring ("OmniRig: " + rig_->StatusStr ());
|
||||
}
|
||||
await_notification_with_timeout (1000);
|
||||
update_rx_frequency (rig_->GetRxFrequency ());
|
||||
qDebug () << "Initial state:" << state ();
|
||||
int resolution {0};
|
||||
if (OmniRig::PM_UNKNOWN == rig_->Vfo ()
|
||||
&& (writable_params_ & (OmniRig::PM_VFOA | OmniRig::PM_VFOB))
|
||||
== (OmniRig::PM_VFOA | OmniRig::PM_VFOB))
|
||||
{
|
||||
// start with VFO A (probably MAIN) on rigs that we
|
||||
// can't query VFO but can set explicitly
|
||||
rig_->SetVfo (OmniRig::PM_VFOA);
|
||||
}
|
||||
auto f = state ().frequency ();
|
||||
if (f % 10) return resolution; // 1Hz resolution
|
||||
auto test_frequency = f - f % 100 + 55;
|
||||
if (OmniRig::PM_FREQ & writable_params_)
|
||||
{
|
||||
rig_->SetFreq (test_frequency);
|
||||
}
|
||||
else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
|
||||
{
|
||||
rig_->SetFreqB (test_frequency);
|
||||
}
|
||||
else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
|
||||
{
|
||||
rig_->SetFreqA (test_frequency);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw_qstring (tr ("OmniRig: don't know how to set rig frequency"));
|
||||
}
|
||||
if (!await_notification_with_timeout (1000))
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "do_start 1: wait timed out");
|
||||
throw_qstring (tr ("OmniRig: timeout waiting for update from rig"));
|
||||
}
|
||||
switch (rig_->GetRxFrequency () - test_frequency)
|
||||
{
|
||||
case -5: resolution = -1; break; // 10Hz truncated
|
||||
case 5: resolution = 1; break; // 10Hz rounded
|
||||
case -15: resolution = -2; break; // 20Hz truncated
|
||||
case -55: resolution = -2; break; // 100Hz truncated
|
||||
case 45: resolution = 2; break; // 100Hz rounded
|
||||
}
|
||||
if (1 == resolution) // may be 20Hz rounded
|
||||
{
|
||||
test_frequency = f - f % 100 + 51;
|
||||
if (OmniRig::PM_FREQ & writable_params_)
|
||||
{
|
||||
if (OmniRig::PM_UNKNOWN == rig_->Vfo ()
|
||||
&& (writable_params_ & (OmniRig::PM_VFOA | OmniRig::PM_VFOB))
|
||||
== (OmniRig::PM_VFOA | OmniRig::PM_VFOB))
|
||||
{
|
||||
// start with VFO A (probably MAIN) on rigs that we
|
||||
// can't query VFO but can set explicitly
|
||||
rig_->SetVfo (OmniRig::PM_VFOA);
|
||||
}
|
||||
if (f % 10) return resolution; // 1Hz resolution
|
||||
auto test_frequency = f - f % 100 + 55;
|
||||
if (OmniRig::PM_FREQ & writable_params_)
|
||||
{
|
||||
rig_->SetFreq (test_frequency);
|
||||
}
|
||||
else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
|
||||
{
|
||||
rig_->SetFreqB (test_frequency);
|
||||
}
|
||||
else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
|
||||
{
|
||||
rig_->SetFreqA (test_frequency);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw_qstring (tr ("OmniRig: don't know how to set rig frequency"));
|
||||
}
|
||||
switch (rig_->GetRxFrequency () - test_frequency)
|
||||
{
|
||||
case -5: resolution = -1; break; // 10Hz truncated
|
||||
case 5: resolution = 1; break; // 10Hz rounded
|
||||
case -15: resolution = -2; break; // 20Hz truncated
|
||||
case -55: resolution = -2; break; // 100Hz truncated
|
||||
case 45: resolution = 2; break; // 100Hz rounded
|
||||
}
|
||||
if (1 == resolution) // may be 20Hz rounded
|
||||
{
|
||||
test_frequency = f - f % 100 + 51;
|
||||
if (OmniRig::PM_FREQ & writable_params_)
|
||||
{
|
||||
rig_->SetFreq (test_frequency);
|
||||
}
|
||||
else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
|
||||
{
|
||||
rig_->SetFreqB (test_frequency);
|
||||
}
|
||||
else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
|
||||
{
|
||||
rig_->SetFreqA (test_frequency);
|
||||
}
|
||||
if (9 == rig_->GetRxFrequency () - test_frequency)
|
||||
{
|
||||
resolution = 2; // 20Hz rounded
|
||||
}
|
||||
}
|
||||
if (OmniRig::PM_FREQ & writable_params_)
|
||||
{
|
||||
rig_->SetFreq (f);
|
||||
}
|
||||
else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
|
||||
{
|
||||
rig_->SetFreqB (f);
|
||||
}
|
||||
else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
|
||||
{
|
||||
rig_->SetFreqA (f);
|
||||
}
|
||||
update_rx_frequency (f);
|
||||
return resolution;
|
||||
rig_->SetFreq (test_frequency);
|
||||
}
|
||||
else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
|
||||
{
|
||||
rig_->SetFreqB (test_frequency);
|
||||
}
|
||||
else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
|
||||
{
|
||||
rig_->SetFreqA (test_frequency);
|
||||
}
|
||||
if (!await_notification_with_timeout (2000))
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "do_start 2: wait timed out");
|
||||
throw_qstring (tr ("OmniRig: timeout waiting for update from rig"));
|
||||
}
|
||||
if (9 == rig_->GetRxFrequency () - test_frequency)
|
||||
{
|
||||
resolution = 2; // 20Hz rounded
|
||||
}
|
||||
}
|
||||
throw_qstring (tr ("OmniRig: Initialization timed out"));
|
||||
return 0; // keep compiler happy
|
||||
if (OmniRig::PM_FREQ & writable_params_)
|
||||
{
|
||||
rig_->SetFreq (f);
|
||||
}
|
||||
else if (reversed_ && (OmniRig::PM_FREQB & writable_params_))
|
||||
{
|
||||
rig_->SetFreqB (f);
|
||||
}
|
||||
else if (!reversed_ && (OmniRig::PM_FREQA & writable_params_))
|
||||
{
|
||||
rig_->SetFreqA (f);
|
||||
}
|
||||
update_rx_frequency (f);
|
||||
return resolution;
|
||||
}
|
||||
|
||||
void OmniRigTransceiver::do_stop ()
|
||||
{
|
||||
if (offline_timer_)
|
||||
{
|
||||
offline_timer_->stop ();
|
||||
offline_timer_.reset ();
|
||||
}
|
||||
|
||||
QThread::msleep (200); // leave some time for pending
|
||||
// commands at the server end
|
||||
if (port_)
|
||||
@ -300,17 +306,6 @@ void OmniRigTransceiver::do_stop ()
|
||||
TRACE_CAT ("OmniRigTransceiver", "stopped");
|
||||
}
|
||||
|
||||
void OmniRigTransceiver::do_sync (bool force_signal, bool /*no_poll*/)
|
||||
{
|
||||
// nothing much we can do here, we just have to let OmniRig do its
|
||||
// stuff and its first poll should send us and update that will
|
||||
// trigger a update signal from us. Any attempt to query OmniRig
|
||||
// leads to a whole mess of trouble since its internal state is
|
||||
// garbage until it has done its first rig poll.
|
||||
send_update_signal_ = force_signal;
|
||||
update_complete ();
|
||||
}
|
||||
|
||||
void OmniRigTransceiver::handle_COM_exception (int code, QString source, QString desc, QString help)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", QString::number (code) + " at " + source + ": " + desc + " (" + help + ')');
|
||||
@ -319,16 +314,20 @@ void OmniRigTransceiver::handle_COM_exception (int code, QString source, QString
|
||||
|
||||
void OmniRigTransceiver::handle_visible_change ()
|
||||
{
|
||||
if (!omni_rig_ || omni_rig_->isNull ()) return;
|
||||
TRACE_CAT ("OmniRigTransceiver", "visibility change: visibility =" << omni_rig_->DialogVisible ());
|
||||
}
|
||||
|
||||
void OmniRigTransceiver::handle_rig_type_change (int rig_number)
|
||||
{
|
||||
if (!omni_rig_ || omni_rig_->isNull ()) return;
|
||||
TRACE_CAT ("OmniRigTransceiver", "rig type change: rig =" << rig_number);
|
||||
if (rig_number_ == rig_number)
|
||||
{
|
||||
if (!rig_ || rig_->isNull ()) return;
|
||||
readable_params_ = rig_->ReadableParams ();
|
||||
writable_params_ = rig_->WriteableParams ();
|
||||
TRACE_CAT ("OmniRigTransceiver", QString {"OmniRig rig type change to: %1 readable params = 0x%2 writable params = 0x%3 for rig %4"}
|
||||
TRACE_CAT ("OmniRigTransceiver", QString {"rig type change to: %1 readable params = 0x%2 writable params = 0x%3 for rig %4"}
|
||||
.arg (rig_->RigType ())
|
||||
.arg (readable_params_, 8, 16, QChar ('0'))
|
||||
.arg (writable_params_, 8, 16, QChar ('0'))
|
||||
@ -338,48 +337,43 @@ void OmniRigTransceiver::handle_rig_type_change (int rig_number)
|
||||
|
||||
void OmniRigTransceiver::handle_status_change (int rig_number)
|
||||
{
|
||||
if (!omni_rig_ || omni_rig_->isNull ()) return;
|
||||
TRACE_CAT ("OmniRigTransceiver", QString {"status change for rig %1"}.arg (rig_number).toLocal8Bit ());
|
||||
if (rig_number_ == rig_number)
|
||||
{
|
||||
if (!rig_ || rig_->isNull ()) return;
|
||||
auto const& status = rig_->StatusStr ().toLocal8Bit ();
|
||||
TRACE_CAT ("OmniRigTransceiver", QString {"OmniRig status change: new status for rig %1 = "}.arg (rig_number).toLocal8Bit () << status);
|
||||
TRACE_CAT ("OmniRigTransceiver", "OmniRig status change: new status = " << status);
|
||||
if (OmniRig::ST_ONLINE != rig_->Status ())
|
||||
{
|
||||
if (!offline_timer_->isActive ())
|
||||
{
|
||||
offline_timer_->start (); // give OmniRig time to recover
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offline_timer_->stop ();
|
||||
update_rx_frequency (rig_->GetRxFrequency ());
|
||||
update_complete ();
|
||||
TRACE_CAT ("OmniRigTransceiver", "OmniRig frequency:" << state ().frequency ());
|
||||
offline ("Rig went offline");
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// update_rx_frequency (rig_->GetRxFrequency ());
|
||||
// update_complete ();
|
||||
// TRACE_CAT ("OmniRigTransceiver", "frequency:" << state ().frequency ());
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
void OmniRigTransceiver::timeout_check ()
|
||||
{
|
||||
offline ("Rig went offline");
|
||||
}
|
||||
|
||||
void OmniRigTransceiver::handle_params_change (int rig_number, int params)
|
||||
{
|
||||
if (rig_number_ == rig_number)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", QString {"OmniRig params change: params = 0x%1 for rig %2"}
|
||||
if (!omni_rig_ || omni_rig_->isNull ()) return;
|
||||
TRACE_CAT ("OmniRigTransceiver", QString {"params change: params = 0x%1 for rig %2"}
|
||||
.arg (params, 8, 16, QChar ('0'))
|
||||
.arg (rig_number).toLocal8Bit ()
|
||||
<< "state before:" << state ());
|
||||
if (rig_number_ == rig_number)
|
||||
{
|
||||
if (!rig_ || rig_->isNull ()) return;
|
||||
// starting_ = false;
|
||||
TransceiverState old_state {state ()};
|
||||
auto need_frequency = false;
|
||||
// state_.online = true; // sometimes we don't get an initial
|
||||
// // OmniRig::ST_ONLINE status change
|
||||
// // event
|
||||
|
||||
if (params & OmniRig::PM_VFOAA)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "VFOAA");
|
||||
update_split (false);
|
||||
reversed_ = false;
|
||||
update_rx_frequency (rig_->FreqA ());
|
||||
@ -387,6 +381,7 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params)
|
||||
}
|
||||
if (params & OmniRig::PM_VFOAB)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "VFOAB");
|
||||
update_split (true);
|
||||
reversed_ = false;
|
||||
update_rx_frequency (rig_->FreqA ());
|
||||
@ -394,6 +389,7 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params)
|
||||
}
|
||||
if (params & OmniRig::PM_VFOBA)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "VFOBA");
|
||||
update_split (true);
|
||||
reversed_ = true;
|
||||
update_other_frequency (rig_->FreqA ());
|
||||
@ -401,6 +397,7 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params)
|
||||
}
|
||||
if (params & OmniRig::PM_VFOBB)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "VFOBB");
|
||||
update_split (false);
|
||||
reversed_ = true;
|
||||
update_other_frequency (rig_->FreqA ());
|
||||
@ -408,64 +405,75 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params)
|
||||
}
|
||||
if (params & OmniRig::PM_VFOA)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "VFOA");
|
||||
reversed_ = false;
|
||||
need_frequency = true;
|
||||
}
|
||||
if (params & OmniRig::PM_VFOB)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "VFOB");
|
||||
reversed_ = true;
|
||||
need_frequency = true;
|
||||
}
|
||||
|
||||
if (params & OmniRig::PM_FREQ)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "FREQ");
|
||||
need_frequency = true;
|
||||
}
|
||||
if (params & OmniRig::PM_FREQA)
|
||||
{
|
||||
auto f = rig_->FreqA ();
|
||||
TRACE_CAT ("OmniRigTransceiver", "FREQA = " << f);
|
||||
if (reversed_)
|
||||
{
|
||||
update_other_frequency (rig_->FreqA ());
|
||||
update_other_frequency (f);
|
||||
}
|
||||
else
|
||||
{
|
||||
update_rx_frequency (rig_->FreqA ());
|
||||
update_rx_frequency (f);
|
||||
}
|
||||
}
|
||||
if (params & OmniRig::PM_FREQB)
|
||||
{
|
||||
auto f = rig_->FreqB ();
|
||||
TRACE_CAT ("OmniRigTransceiver", "FREQB = " << f);
|
||||
if (reversed_)
|
||||
{
|
||||
update_rx_frequency (rig_->FreqB ());
|
||||
update_rx_frequency (f);
|
||||
}
|
||||
else
|
||||
{
|
||||
update_other_frequency (rig_->FreqB ());
|
||||
update_other_frequency (f);
|
||||
}
|
||||
}
|
||||
if (need_frequency)
|
||||
{
|
||||
if (readable_params_ & OmniRig::PM_FREQA)
|
||||
{
|
||||
auto f = rig_->FreqA ();
|
||||
TRACE_CAT ("OmniRigTransceiver", "FREQA = " << f);
|
||||
if (reversed_)
|
||||
{
|
||||
update_other_frequency (rig_->FreqA ());
|
||||
update_other_frequency (f);
|
||||
}
|
||||
else
|
||||
{
|
||||
update_rx_frequency (rig_->FreqA ());
|
||||
update_rx_frequency (f);
|
||||
}
|
||||
need_frequency = false;
|
||||
}
|
||||
if (readable_params_ & OmniRig::PM_FREQB)
|
||||
{
|
||||
auto f = rig_->FreqB ();
|
||||
TRACE_CAT ("OmniRigTransceiver", "FREQB = " << f);
|
||||
if (reversed_)
|
||||
{
|
||||
update_rx_frequency (rig_->FreqB ());
|
||||
update_rx_frequency (f);
|
||||
}
|
||||
else
|
||||
{
|
||||
update_other_frequency (rig_->FreqB ());
|
||||
update_other_frequency (f);
|
||||
}
|
||||
need_frequency = false;
|
||||
}
|
||||
@ -473,89 +481,113 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params)
|
||||
if (need_frequency && (readable_params_ & OmniRig::PM_FREQ)
|
||||
&& !state ().ptt ())
|
||||
{
|
||||
update_rx_frequency (rig_->Freq ());
|
||||
auto f = rig_->Freq ();
|
||||
TRACE_CAT ("OmniRigTransceiver", "FREQ = " << f);
|
||||
update_rx_frequency (f);
|
||||
}
|
||||
if (params & OmniRig::PM_PITCH)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "PITCH");
|
||||
}
|
||||
if (params & OmniRig::PM_RITOFFSET)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "RITOFFSET");
|
||||
}
|
||||
if (params & OmniRig::PM_RIT0)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "RIT0");
|
||||
}
|
||||
if (params & OmniRig::PM_VFOEQUAL)
|
||||
{
|
||||
auto f = readable_params_ & OmniRig::PM_FREQA ? rig_->FreqA () : rig_->Freq ();
|
||||
auto m = map_mode (rig_->Mode ());
|
||||
TRACE_CAT ("OmniRigTransceiver", QString {"VFOEQUAL f=%1 m=%2"}.arg (f).arg (m));
|
||||
update_rx_frequency (f);
|
||||
update_other_frequency (f);
|
||||
update_mode (map_mode (rig_->Mode ()));
|
||||
update_mode (m);
|
||||
}
|
||||
if (params & OmniRig::PM_VFOSWAP)
|
||||
{
|
||||
auto temp = state ().tx_frequency ();
|
||||
TRACE_CAT ("OmniRigTransceiver", "VFOSWAP");
|
||||
auto f = state ().tx_frequency ();
|
||||
update_other_frequency (state ().frequency ());
|
||||
update_rx_frequency (temp);
|
||||
update_rx_frequency (f);
|
||||
update_mode (map_mode (rig_->Mode ()));
|
||||
}
|
||||
if (params & OmniRig::PM_SPLITON)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "SPLITON");
|
||||
update_split (true);
|
||||
}
|
||||
if (params & OmniRig::PM_SPLITOFF)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "SPLITOFF");
|
||||
update_split (false);
|
||||
}
|
||||
if (params & OmniRig::PM_RITON)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "RITON");
|
||||
}
|
||||
if (params & OmniRig::PM_RITOFF)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "RITOFF");
|
||||
}
|
||||
if (params & OmniRig::PM_XITON)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "XITON");
|
||||
}
|
||||
if (params & OmniRig::PM_XITOFF)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "XITOFF");
|
||||
}
|
||||
if (params & OmniRig::PM_RX)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "RX");
|
||||
update_PTT (false);
|
||||
}
|
||||
if (params & OmniRig::PM_TX)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "TX");
|
||||
update_PTT ();
|
||||
}
|
||||
if (params & OmniRig::PM_CW_U)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "CW-R");
|
||||
update_mode (CW_R);
|
||||
}
|
||||
if (params & OmniRig::PM_CW_L)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "CW");
|
||||
update_mode (CW);
|
||||
}
|
||||
if (params & OmniRig::PM_SSB_U)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "USB");
|
||||
update_mode (USB);
|
||||
}
|
||||
if (params & OmniRig::PM_SSB_L)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "LSB");
|
||||
update_mode (LSB);
|
||||
}
|
||||
if (params & OmniRig::PM_DIG_U)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "DATA-U");
|
||||
update_mode (DIG_U);
|
||||
}
|
||||
if (params & OmniRig::PM_DIG_L)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "DATA-L");
|
||||
update_mode (DIG_L);
|
||||
}
|
||||
if (params & OmniRig::PM_AM)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "AM");
|
||||
update_mode (AM);
|
||||
}
|
||||
if (params & OmniRig::PM_FM)
|
||||
{
|
||||
TRACE_CAT ("OmniRigTransceiver", "FM");
|
||||
update_mode (FM);
|
||||
}
|
||||
|
||||
@ -566,6 +598,7 @@ void OmniRigTransceiver::handle_params_change (int rig_number, int params)
|
||||
}
|
||||
TRACE_CAT ("OmniRigTransceiver", "OmniRig params change: state after:" << state ());
|
||||
}
|
||||
Q_EMIT notified ();
|
||||
}
|
||||
|
||||
void OmniRigTransceiver::handle_custom_reply (int rig_number, QVariant const& command, QVariant const& reply)
|
||||
@ -573,8 +606,10 @@ void OmniRigTransceiver::handle_custom_reply (int rig_number, QVariant const& co
|
||||
(void)command;
|
||||
(void)reply;
|
||||
|
||||
if (!omni_rig_ || omni_rig_->isNull ()) return;
|
||||
if (rig_number_ == rig_number)
|
||||
{
|
||||
if (!rig_ || rig_->isNull ()) return;
|
||||
TRACE_CAT ("OmniRigTransceiver", "custom command" << command.toString ().toLocal8Bit ()
|
||||
<< "with reply" << reply.toString ().toLocal8Bit ()
|
||||
<< QString ("for rig %1").arg (rig_number).toLocal8Bit ());
|
||||
|
@ -38,10 +38,11 @@ public:
|
||||
void do_tx_frequency (Frequency, MODE, bool no_ignore) override;
|
||||
void do_mode (MODE) override;
|
||||
void do_ptt (bool on) override;
|
||||
void do_sync (bool force_signal, bool no_poll) override;
|
||||
|
||||
private:
|
||||
Q_SLOT void timeout_check ();
|
||||
bool await_notification_with_timeout (int timeout);
|
||||
Q_SIGNAL void notified () const;
|
||||
// Q_SLOT void timeout_check ();
|
||||
Q_SLOT void handle_COM_exception (int, QString, QString, QString);
|
||||
Q_SLOT void handle_visible_change ();
|
||||
Q_SLOT void handle_rig_type_change (int rig_number);
|
||||
@ -62,7 +63,7 @@ private:
|
||||
QString rig_type_;
|
||||
int readable_params_;
|
||||
int writable_params_;
|
||||
QScopedPointer<QTimer> offline_timer_;
|
||||
// QScopedPointer<QTimer> offline_timer_;
|
||||
bool send_update_signal_;
|
||||
bool reversed_; // some rigs can reverse VFOs
|
||||
};
|
||||
|
@ -129,52 +129,46 @@ bool PollingTransceiver::do_pre_update ()
|
||||
return true;
|
||||
}
|
||||
|
||||
void PollingTransceiver::do_sync (bool force_signal, bool no_poll)
|
||||
{
|
||||
if (!no_poll) poll (); // tell sub-classes to update our state
|
||||
|
||||
// Signal new state if it is directly requested or, what we expected
|
||||
// or, hasn't become what we expected after polls_to_stabilize
|
||||
// polls. Unsolicited changes will be signalled immediately unless
|
||||
// they intervene in a expected sequence where they will be delayed.
|
||||
if (retries_)
|
||||
{
|
||||
--retries_;
|
||||
if (force_signal || state () == next_state_ || !retries_)
|
||||
{
|
||||
// our client wants a signal regardless
|
||||
// or the expected state has arrived
|
||||
// or there are no more retries
|
||||
force_signal = true;
|
||||
}
|
||||
}
|
||||
else if (force_signal || state () != last_signalled_state_)
|
||||
{
|
||||
// here is the normal passive polling path either our client has
|
||||
// requested a state update regardless of change or state has
|
||||
// changed asynchronously
|
||||
force_signal = true;
|
||||
}
|
||||
|
||||
if (force_signal)
|
||||
{
|
||||
// reset everything, record and signal the current state
|
||||
retries_ = 0;
|
||||
next_state_ = state ();
|
||||
last_signalled_state_ = state ();
|
||||
update_complete (true);
|
||||
}
|
||||
}
|
||||
|
||||
void PollingTransceiver::handle_timeout ()
|
||||
{
|
||||
QString message;
|
||||
bool force_signal {false};
|
||||
|
||||
// we must catch all exceptions here since we are called by Qt and
|
||||
// inform our parent of the failure via the offline() message
|
||||
try
|
||||
{
|
||||
do_sync ();
|
||||
do_poll (); // tell sub-classes to update our state
|
||||
|
||||
// Signal new state if it what we expected or, hasn't become
|
||||
// what we expected after polls_to_stabilize polls. Unsolicited
|
||||
// changes will be signalled immediately unless they intervene
|
||||
// in a expected sequence where they will be delayed.
|
||||
if (retries_)
|
||||
{
|
||||
--retries_;
|
||||
if (state () == next_state_ || !retries_)
|
||||
{
|
||||
// the expected state has arrived or there are no more
|
||||
// retries
|
||||
force_signal = true;
|
||||
}
|
||||
}
|
||||
else if (state () != last_signalled_state_)
|
||||
{
|
||||
// here is the normal passive polling path where state has
|
||||
// changed asynchronously
|
||||
force_signal = true;
|
||||
}
|
||||
|
||||
if (force_signal)
|
||||
{
|
||||
// reset everything, record and signal the current state
|
||||
retries_ = 0;
|
||||
next_state_ = state ();
|
||||
last_signalled_state_ = state ();
|
||||
update_complete (true);
|
||||
}
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
|
@ -39,11 +39,9 @@ protected:
|
||||
QObject * parent);
|
||||
|
||||
protected:
|
||||
void do_sync (bool force_signal = false, bool no_poll = false) override final;
|
||||
|
||||
// Sub-classes implement this and fetch what they can from the rig
|
||||
// in a non-intrusive manner.
|
||||
virtual void poll () = 0;
|
||||
virtual void do_poll () = 0;
|
||||
|
||||
void do_post_start () override final;
|
||||
void do_post_stop () override final;
|
||||
|
@ -74,14 +74,14 @@ namespace Radio
|
||||
}
|
||||
|
||||
|
||||
QString frequency_MHz_string (Frequency f, QLocale const& locale)
|
||||
QString frequency_MHz_string (Frequency f, int precision, QLocale const& locale)
|
||||
{
|
||||
return locale.toString (f / MHz_factor, 'f', frequency_precsion);
|
||||
return locale.toString (f / MHz_factor, 'f', precision);
|
||||
}
|
||||
|
||||
QString frequency_MHz_string (FrequencyDelta d, QLocale const& locale)
|
||||
QString frequency_MHz_string (FrequencyDelta d, int precision, QLocale const& locale)
|
||||
{
|
||||
return locale.toString (d / MHz_factor, 'f', frequency_precsion);
|
||||
return locale.toString (d / MHz_factor, 'f', precision);
|
||||
}
|
||||
|
||||
QString pretty_frequency_MHz_string (Frequency f, QLocale const& locale)
|
||||
|
@ -42,8 +42,8 @@ namespace Radio
|
||||
//
|
||||
// Frequency type formatting
|
||||
//
|
||||
QString UDP_EXPORT frequency_MHz_string (Frequency, QLocale const& = QLocale ());
|
||||
QString UDP_EXPORT frequency_MHz_string (FrequencyDelta, QLocale const& = QLocale ());
|
||||
QString UDP_EXPORT frequency_MHz_string (Frequency, int precision = 6, QLocale const& = QLocale ());
|
||||
QString UDP_EXPORT frequency_MHz_string (FrequencyDelta, int precision = 6, QLocale const& = QLocale ());
|
||||
QString UDP_EXPORT pretty_frequency_MHz_string (Frequency, QLocale const& = QLocale ());
|
||||
QString UDP_EXPORT pretty_frequency_MHz_string (double, int scale, QLocale const& = QLocale ());
|
||||
QString UDP_EXPORT pretty_frequency_MHz_string (FrequencyDelta, QLocale const& = QLocale ());
|
||||
|
@ -40,6 +40,8 @@ OTHER IMPROVEMENTS
|
||||
- N1MM Logger+ now uses the standard WSJT-X UDP messages
|
||||
- OK/Cancel buttons on Log QSO window maintain fixed positions
|
||||
- Put EU VHF contest serial numbers into the ADIF SRX and STX fields
|
||||
- Enhancements to the Omni-Rig CAT interface
|
||||
- New setting option to include or exclude WAE entities
|
||||
|
||||
BUG FIXES
|
||||
- Fix generation of Tx5 message when one callsign is nonstandard
|
||||
@ -47,6 +49,7 @@ BUG FIXES
|
||||
- Fix a bug that caused mode switch from FT4 to FT8
|
||||
- Fix a bug that caused FT4 to do WSPR-style band hopping
|
||||
- Fix a bug that caused a Fortran bounds error
|
||||
- Repaired field editing in the Contest Log window
|
||||
|
||||
Release candidate WSJT-X 2.1.0-rc6 will be available for beta-testing
|
||||
through July 21, 2019. It will be inoperable during the ARRL June VHF
|
||||
|
@ -19,10 +19,10 @@ void TransceiverBase::start (unsigned sequence_number) noexcept
|
||||
QString message;
|
||||
try
|
||||
{
|
||||
last_sequence_number_ = sequence_number;
|
||||
may_update u {this, true};
|
||||
shutdown ();
|
||||
startup ();
|
||||
last_sequence_number_ = sequence_number;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
@ -46,6 +46,7 @@ void TransceiverBase::set (TransceiverState const& s,
|
||||
QString message;
|
||||
try
|
||||
{
|
||||
last_sequence_number_ = sequence_number;
|
||||
may_update u {this, true};
|
||||
bool was_online {requested_.online ()};
|
||||
if (!s.online () && was_online)
|
||||
@ -115,7 +116,6 @@ void TransceiverBase::set (TransceiverState const& s,
|
||||
// record what actually changed
|
||||
requested_.ptt (actual_.ptt ());
|
||||
}
|
||||
last_sequence_number_ = sequence_number;
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
@ -133,10 +133,27 @@ void TransceiverBase::set (TransceiverState const& s,
|
||||
|
||||
void TransceiverBase::startup ()
|
||||
{
|
||||
Q_EMIT resolution (do_start ());
|
||||
do_post_start ();
|
||||
actual_.online (true);
|
||||
requested_.online (true);
|
||||
QString message;
|
||||
try
|
||||
{
|
||||
actual_.online (true);
|
||||
requested_.online (true);
|
||||
auto res = do_start ();
|
||||
do_post_start ();
|
||||
Q_EMIT resolution (res);
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
message = e.what ();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
message = unexpected;
|
||||
}
|
||||
if (!message.isEmpty ())
|
||||
{
|
||||
offline (message);
|
||||
}
|
||||
}
|
||||
|
||||
void TransceiverBase::shutdown ()
|
||||
@ -163,8 +180,8 @@ void TransceiverBase::shutdown ()
|
||||
}
|
||||
do_stop ();
|
||||
do_post_stop ();
|
||||
actual_.online (false);
|
||||
requested_.online (false);
|
||||
actual_ = TransceiverState {};
|
||||
requested_ = TransceiverState {};
|
||||
}
|
||||
|
||||
void TransceiverBase::stop () noexcept
|
||||
|
@ -112,8 +112,6 @@ protected:
|
||||
virtual void do_ptt (bool = true) = 0;
|
||||
virtual void do_post_ptt (bool = true) {}
|
||||
|
||||
virtual void do_sync (bool force_signal = false, bool no_poll = false) = 0;
|
||||
|
||||
virtual bool do_pre_update () {return true;}
|
||||
|
||||
// sub classes report rig state changes with these methods
|
||||
|
@ -2,5 +2,5 @@
|
||||
set (WSJTX_VERSION_MAJOR 2)
|
||||
set (WSJTX_VERSION_MINOR 1)
|
||||
set (WSJTX_VERSION_PATCH 0)
|
||||
set (WSJTX_RC 6) # release candidate number, comment out or zero for development versions
|
||||
set (WSJTX_RC 7) # release candidate number, comment out or zero for development versions
|
||||
set (WSJTX_VERSION_IS_RELEASE 0) # set to 1 for final release build
|
||||
|
27
item_delegates/FrequencyDelegate.cpp
Normal file
27
item_delegates/FrequencyDelegate.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "FrequencyDelegate.hpp"
|
||||
|
||||
#include "widgets/FrequencyLineEdit.hpp"
|
||||
|
||||
FrequencyDelegate::FrequencyDelegate (QObject * parent)
|
||||
: QStyledItemDelegate {parent}
|
||||
{
|
||||
}
|
||||
|
||||
QWidget * FrequencyDelegate::createEditor (QWidget * parent, QStyleOptionViewItem const&
|
||||
, QModelIndex const&) const
|
||||
{
|
||||
auto * editor = new FrequencyLineEdit {parent};
|
||||
editor->setFrame (false);
|
||||
return editor;
|
||||
}
|
||||
|
||||
void FrequencyDelegate::setEditorData (QWidget * editor, QModelIndex const& index) const
|
||||
{
|
||||
static_cast<FrequencyLineEdit *> (editor)->frequency (index.model ()->data (index, Qt::EditRole).value<Radio::Frequency> ());
|
||||
}
|
||||
|
||||
void FrequencyDelegate::setModelData (QWidget * editor, QAbstractItemModel * model, QModelIndex const& index) const
|
||||
{
|
||||
model->setData (index, static_cast<FrequencyLineEdit *> (editor)->frequency (), Qt::EditRole);
|
||||
}
|
||||
|
21
item_delegates/FrequencyDelegate.hpp
Normal file
21
item_delegates/FrequencyDelegate.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef FREQUENCY_DELEGATE_HPP_
|
||||
#define FREQUENCY_DELEGATE_HPP_
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
//
|
||||
// Class FrequencyDelegate
|
||||
//
|
||||
// Item delegate for editing a frequency in Hertz but displayed in MHz
|
||||
//
|
||||
class FrequencyDelegate final
|
||||
: public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
explicit FrequencyDelegate (QObject * parent = nullptr);
|
||||
QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
|
||||
void setEditorData (QWidget * editor, QModelIndex const&) const override;
|
||||
void setModelData (QWidget * editor, QAbstractItemModel *, QModelIndex const&) const override;
|
||||
};
|
||||
|
||||
#endif
|
26
item_delegates/FrequencyDeltaDelegate.cpp
Normal file
26
item_delegates/FrequencyDeltaDelegate.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "FrequencyDeltaDelegate.hpp"
|
||||
|
||||
#include "widgets/FrequencyDeltaLineEdit.hpp"
|
||||
|
||||
FrequencyDeltaDelegate::FrequencyDeltaDelegate (QObject * parent)
|
||||
: QStyledItemDelegate {parent}
|
||||
{
|
||||
}
|
||||
|
||||
QWidget * FrequencyDeltaDelegate::createEditor (QWidget * parent, QStyleOptionViewItem const&
|
||||
, QModelIndex const&) const
|
||||
{
|
||||
auto * editor = new FrequencyDeltaLineEdit {parent};
|
||||
editor->setFrame (false);
|
||||
return editor;
|
||||
}
|
||||
|
||||
void FrequencyDeltaDelegate::setEditorData (QWidget * editor, QModelIndex const& index) const
|
||||
{
|
||||
static_cast<FrequencyDeltaLineEdit *> (editor)->frequency_delta (index.model ()->data (index, Qt::EditRole).value<Radio::FrequencyDelta> ());
|
||||
}
|
||||
|
||||
void FrequencyDeltaDelegate::setModelData (QWidget * editor, QAbstractItemModel * model, QModelIndex const& index) const
|
||||
{
|
||||
model->setData (index, static_cast<FrequencyDeltaLineEdit *> (editor)->frequency_delta (), Qt::EditRole);
|
||||
}
|
21
item_delegates/FrequencyDeltaDelegate.hpp
Normal file
21
item_delegates/FrequencyDeltaDelegate.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef FREQUENCY_DELTA_DELEGATE_HPP_
|
||||
#define FREQUENCY_DELTA_DELEGATE_HPP_
|
||||
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
//
|
||||
// Class FrequencyDeltaDelegate
|
||||
//
|
||||
// Item delegate for editing a frequency delta in Hertz but displayed in MHz
|
||||
//
|
||||
class FrequencyDeltaDelegate final
|
||||
: public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
explicit FrequencyDeltaDelegate (QObject * parent = nullptr);
|
||||
QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const&, QModelIndex const&) const override;
|
||||
void setEditorData (QWidget * editor, QModelIndex const&) const override;
|
||||
void setModelData (QWidget * editor, QAbstractItemModel *, QModelIndex const&) const override;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,11 +1,13 @@
|
||||
SOURCES += \
|
||||
item_delegates/ForeignKeyDelegate.cpp \
|
||||
item_delegates/FrequencyItemDelegate.cpp \
|
||||
item_delegates/FrequencyDelegate.cpp \
|
||||
item_delegates/FrequencyDeltaDelegate.cpp \
|
||||
item_delegates/CallsignDelegate.cpp \
|
||||
item_delegates/MaidenheadLocatorItemDelegate.cpp
|
||||
|
||||
HEADERS += \
|
||||
item_delegates/ForeignKeyDelegate.hpp \
|
||||
item_delegates/FrequencyItemDelegate.hpp \
|
||||
item_delegates/FrequencyDelegate.hpp \
|
||||
item_delegates/FrequencyDeltaDelegate.hpp \
|
||||
item_delegates/CallsignDelegate.hpp \
|
||||
item_delegates/MaidenheadLocatorDelegate.hpp
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include <QTextStream>
|
||||
#include <QDebug>
|
||||
#include <QDebugStateSaver>
|
||||
#include "Configuration.hpp"
|
||||
#include "Radio.hpp"
|
||||
#include "pimpl_impl.hpp"
|
||||
|
||||
@ -155,14 +156,16 @@ typedef multi_index_container<
|
||||
class AD1CCty::impl final
|
||||
{
|
||||
public:
|
||||
explicit impl ()
|
||||
using entity_by_id = entities_type::index<id>::type;
|
||||
|
||||
explicit impl (Configuration const * configuration)
|
||||
: configuration_ {configuration}
|
||||
{
|
||||
}
|
||||
|
||||
Record fixup (QString call, prefix const& p) const
|
||||
entity_by_id::iterator lookup_entity (QString call, prefix const& p) const
|
||||
{
|
||||
call = call.toUpper ();
|
||||
using entity_by_id = entities_type::index<id>::type;
|
||||
entity_by_id::iterator e; // iterator into entity set
|
||||
|
||||
//
|
||||
@ -171,23 +174,26 @@ public:
|
||||
if (call.startsWith ("KG4") && call.size () != 5 && call.size () != 3)
|
||||
{
|
||||
// KG4 2x1 and 2x3 calls that map to Gitmo are mainland US not Gitmo
|
||||
e = entities_.project<id> (entities_.get<primary_prefix> ().find ("K"));
|
||||
return entities_.project<id> (entities_.get<primary_prefix> ().find ("K"));
|
||||
}
|
||||
else
|
||||
{
|
||||
e = entities_.get<id> ().find (p.entity_id_);
|
||||
return entities_.get<id> ().find (p.entity_id_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Record fixup (prefix const& p, entity const& e) const
|
||||
{
|
||||
Record result;
|
||||
result.continent = e->continent_;
|
||||
result.CQ_zone = e->CQ_zone_;
|
||||
result.ITU_zone = e->ITU_zone_;
|
||||
result.entity_name = e->name_;
|
||||
result.WAE_only = e->WAE_only_;
|
||||
result.latitude = e->lat_;
|
||||
result.longtitude = e->long_;
|
||||
result.UTC_offset = e->UTC_offset_;
|
||||
result.primary_prefix = e->primary_prefix_;
|
||||
result.continent = e.continent_;
|
||||
result.CQ_zone = e.CQ_zone_;
|
||||
result.ITU_zone = e.ITU_zone_;
|
||||
result.entity_name = e.name_;
|
||||
result.WAE_only = e.WAE_only_;
|
||||
result.latitude = e.lat_;
|
||||
result.longtitude = e.long_;
|
||||
result.UTC_offset = e.UTC_offset_;
|
||||
result.primary_prefix = e.primary_prefix_;
|
||||
|
||||
// check for overrides
|
||||
bool ok1 {true}, ok2 {true}, ok3 {true}, ok4 {true}, ok5 {true};
|
||||
@ -220,6 +226,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
Configuration const * configuration_;
|
||||
QString path_;
|
||||
entities_type entities_;
|
||||
prefixes_type prefixes_;
|
||||
@ -307,8 +314,13 @@ char const * AD1CCty::continent (Continent c)
|
||||
}
|
||||
}
|
||||
|
||||
AD1CCty::AD1CCty ()
|
||||
AD1CCty::AD1CCty (Configuration const * configuration)
|
||||
: m_ {configuration}
|
||||
{
|
||||
Q_ASSERT (configuration);
|
||||
// TODO: G4WJS - consider doing the following asynchronously to
|
||||
// speed up startup. Not urgent as it takes less than 1s on a Core
|
||||
// i7 reading BIG CTY.DAT.
|
||||
QDir dataPath {QStandardPaths::writableLocation (QStandardPaths::DataLocation)};
|
||||
m_->path_ = dataPath.exists (file_name)
|
||||
? dataPath.absoluteFilePath (file_name) // user override
|
||||
@ -389,7 +401,7 @@ auto AD1CCty::lookup (QString const& call) const -> Record
|
||||
auto p = m_->prefixes_.find (exact_search);
|
||||
if (p != m_->prefixes_.end () && p->exact_)
|
||||
{
|
||||
return m_->fixup (call, *p);
|
||||
return m_->fixup (*p, *m_->lookup_entity (call, *p));
|
||||
}
|
||||
}
|
||||
while (search_prefix.size ())
|
||||
@ -397,9 +409,11 @@ auto AD1CCty::lookup (QString const& call) const -> Record
|
||||
auto p = m_->prefixes_.find (search_prefix);
|
||||
if (p != m_->prefixes_.end ())
|
||||
{
|
||||
if (!p->exact_ || call.size () == search_prefix.size ())
|
||||
impl::entity_by_id::iterator e = m_->lookup_entity (call, *p);
|
||||
if ((m_->configuration_->include_WAE_entities () || !e->WAE_only_)
|
||||
&& (!p->exact_ || call.size () == search_prefix.size ()))
|
||||
{
|
||||
return m_->fixup (call, *p);
|
||||
return m_->fixup (*p, *e);
|
||||
}
|
||||
}
|
||||
search_prefix = search_prefix.left (search_prefix.size () - 1);
|
||||
|
@ -1,17 +1,19 @@
|
||||
#ifndef AD1C_CTY_HPP_
|
||||
#define AD1C_CTY_HPP_
|
||||
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include "pimpl_h.hpp"
|
||||
|
||||
class QString;
|
||||
class Configuration;
|
||||
|
||||
//
|
||||
// AD1CCty - Fast access database of Jim Reisert, AD1C's, cty.dat
|
||||
// entity and entity override information file.
|
||||
//
|
||||
class AD1CCty final
|
||||
: public QObject
|
||||
, private boost::noncopyable
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@ -39,7 +41,7 @@ public:
|
||||
QString primary_prefix;
|
||||
};
|
||||
|
||||
explicit AD1CCty ();
|
||||
explicit AD1CCty (Configuration const *);
|
||||
~AD1CCty ();
|
||||
Record lookup (QString const& call) const;
|
||||
|
||||
|
44
logbook/Multiplier.cpp
Normal file
44
logbook/Multiplier.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "Multiplier.hpp"
|
||||
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include "models/CabrilloLog.hpp"
|
||||
#include "pimpl_impl.hpp"
|
||||
|
||||
class Multiplier::impl
|
||||
{
|
||||
public:
|
||||
impl (AD1CCty const * countries)
|
||||
: countries_ {countries}
|
||||
{
|
||||
}
|
||||
|
||||
AD1CCty const * countries_;
|
||||
worked_set entities_worked_;
|
||||
worked_set grids_worked_;
|
||||
};
|
||||
|
||||
Multiplier::Multiplier (AD1CCty const * countries)
|
||||
: m_ {countries}
|
||||
{
|
||||
}
|
||||
|
||||
Multiplier::~Multiplier ()
|
||||
{
|
||||
}
|
||||
|
||||
void Multiplier::reload (CabrilloLog const * log)
|
||||
{
|
||||
m_->entities_worked_ = log->unique_DXCC_entities (m_->countries_);
|
||||
}
|
||||
|
||||
auto Multiplier::entities_worked () const -> worked_set const&
|
||||
{
|
||||
return m_->entities_worked_;
|
||||
}
|
||||
|
||||
auto Multiplier::grids_worked () const -> worked_set const&
|
||||
{
|
||||
return m_->grids_worked_;
|
||||
}
|
30
logbook/Multiplier.hpp
Normal file
30
logbook/Multiplier.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef MULTIPLIER_HPP_
|
||||
#define MULTIPLIER_HPP_
|
||||
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
#include <QSet>
|
||||
#include "pimpl_h.hpp"
|
||||
|
||||
class QString;
|
||||
class AD1CCty;
|
||||
class CabrilloLog;
|
||||
|
||||
class Multiplier final
|
||||
: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
using worked_item = QPair<QString, QString>;
|
||||
using worked_set = QSet<worked_item>;
|
||||
|
||||
explicit Multiplier (AD1CCty const *);
|
||||
~Multiplier ();
|
||||
void reload (CabrilloLog const *);
|
||||
worked_set const& entities_worked () const;
|
||||
worked_set const& grids_worked () const;
|
||||
|
||||
private:
|
||||
class impl;
|
||||
pimpl<impl> m_;
|
||||
};
|
||||
|
||||
#endif
|
@ -18,7 +18,7 @@
|
||||
#include <QFileInfo>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
|
||||
#include "Configuration.hpp"
|
||||
#include "qt_helpers.hpp"
|
||||
#include "pimpl_impl.hpp"
|
||||
|
||||
@ -361,8 +361,9 @@ namespace
|
||||
class WorkedBefore::impl final
|
||||
{
|
||||
public:
|
||||
impl ()
|
||||
impl (Configuration const * configuration)
|
||||
: path_ {QDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}.absoluteFilePath (logFileName)}
|
||||
, prefixes_ {configuration}
|
||||
{
|
||||
}
|
||||
|
||||
@ -379,8 +380,10 @@ public:
|
||||
worked_before_database_type worked_;
|
||||
};
|
||||
|
||||
WorkedBefore::WorkedBefore ()
|
||||
WorkedBefore::WorkedBefore (Configuration const * configuration)
|
||||
: m_ {configuration}
|
||||
{
|
||||
Q_ASSERT (configuration);
|
||||
connect (&m_->loader_watcher_, &QFutureWatcher<worked_before_database_type>::finished, [this] () {
|
||||
QString error;
|
||||
size_t n {0};
|
||||
@ -412,9 +415,9 @@ QString const& WorkedBefore::path () const
|
||||
return m_->path_;
|
||||
}
|
||||
|
||||
AD1CCty const& WorkedBefore::countries () const
|
||||
AD1CCty const * WorkedBefore::countries () const
|
||||
{
|
||||
return m_->prefixes_;
|
||||
return &m_->prefixes_;
|
||||
}
|
||||
|
||||
bool WorkedBefore::add (QString const& call
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "AD1CCty.hpp"
|
||||
#include "pimpl_h.hpp"
|
||||
|
||||
class Configuration;
|
||||
class CountryDat;
|
||||
class QString;
|
||||
class QByteArray;
|
||||
@ -17,7 +18,7 @@ class WorkedBefore final
|
||||
public:
|
||||
using Continent = AD1CCty::Continent;
|
||||
|
||||
explicit WorkedBefore ();
|
||||
explicit WorkedBefore (Configuration const *);
|
||||
~WorkedBefore ();
|
||||
|
||||
Q_SLOT void reload ();
|
||||
@ -28,7 +29,7 @@ public:
|
||||
, QByteArray const& ADIF_record);
|
||||
|
||||
QString const& path () const;
|
||||
AD1CCty const& countries () const;
|
||||
AD1CCty const * countries () const;
|
||||
bool country_worked (QString const& call, QString const& mode, QString const& band) const;
|
||||
bool grid_worked (QString const& grid, QString const& mode, QString const& band) const;
|
||||
bool call_worked (QString const& call, QString const& mode, QString const& band) const;
|
||||
|
@ -3,15 +3,25 @@
|
||||
#include <QDateTime>
|
||||
#include "Configuration.hpp"
|
||||
#include "AD1CCty.hpp"
|
||||
#include "Multiplier.hpp"
|
||||
#include "logbook/AD1CCty.hpp"
|
||||
#include "models/CabrilloLog.hpp"
|
||||
#include "models/FoxLog.hpp"
|
||||
|
||||
#include "moc_logbook.cpp"
|
||||
|
||||
LogBook::LogBook (Configuration const * configuration)
|
||||
: config_ {configuration}
|
||||
, worked_before_ {configuration}
|
||||
{
|
||||
Q_ASSERT (configuration);
|
||||
connect (&worked_before_, &WorkedBefore::finished_loading, this, &LogBook::finished_loading);
|
||||
}
|
||||
|
||||
LogBook::~LogBook ()
|
||||
{
|
||||
}
|
||||
|
||||
void LogBook::match (QString const& call, QString const& mode, QString const& grid,
|
||||
AD1CCty::Record const& looked_up,
|
||||
bool& callB4,
|
||||
@ -136,3 +146,40 @@ QByteArray LogBook::QSOToADIF (QString const& hisCall, QString const& hisGrid, Q
|
||||
}
|
||||
return t.toLatin1();
|
||||
}
|
||||
|
||||
CabrilloLog * LogBook::contest_log ()
|
||||
{
|
||||
// lazy create of Cabrillo log object instance
|
||||
if (!contest_log_)
|
||||
{
|
||||
contest_log_.reset (new CabrilloLog {config_});
|
||||
if (!multiplier_)
|
||||
{
|
||||
multiplier_.reset (new Multiplier {countries ()});
|
||||
}
|
||||
connect (contest_log_.data (), &CabrilloLog::data_changed, [this] () {
|
||||
multiplier_->reload (contest_log_.data ());
|
||||
});
|
||||
}
|
||||
return contest_log_.data ();
|
||||
}
|
||||
|
||||
Multiplier const * LogBook::multiplier () const
|
||||
{
|
||||
// lazy create of Multiplier object instance
|
||||
if (!multiplier_)
|
||||
{
|
||||
multiplier_.reset (new Multiplier {countries ()});
|
||||
}
|
||||
return multiplier_.data ();
|
||||
}
|
||||
|
||||
FoxLog * LogBook::fox_log ()
|
||||
{
|
||||
// lazy create of Fox log object instance
|
||||
if (!fox_log_)
|
||||
{
|
||||
fox_log_.reset (new FoxLog {config_});
|
||||
}
|
||||
return fox_log_.data ();
|
||||
}
|
||||
|
@ -8,12 +8,16 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QScopedPointer>
|
||||
|
||||
#include "WorkedBefore.hpp"
|
||||
|
||||
class Configuration;
|
||||
class QByteArray;
|
||||
class QDateTime;
|
||||
class CabrilloLog;
|
||||
class Multiplier;
|
||||
class FoxLog;
|
||||
|
||||
class LogBook final
|
||||
: public QObject
|
||||
@ -22,13 +26,14 @@ class LogBook final
|
||||
|
||||
public:
|
||||
LogBook (Configuration const *);
|
||||
~LogBook ();
|
||||
QString const& path () const {return worked_before_.path ();}
|
||||
bool add (QString const& call
|
||||
, QString const& grid
|
||||
, QString const& band
|
||||
, QString const& mode
|
||||
, QByteArray const& ADIF_record);
|
||||
AD1CCty const& countries () const {return worked_before_.countries ();}
|
||||
AD1CCty const * countries () const {return worked_before_.countries ();}
|
||||
void rescan ();
|
||||
void match (QString const& call, QString const& mode, QString const& grid,
|
||||
AD1CCty::Record const&, bool& callB4, bool& countryB4,
|
||||
@ -43,9 +48,16 @@ public:
|
||||
|
||||
Q_SIGNAL void finished_loading (int worked_before_record_count, QString const& error) const;
|
||||
|
||||
CabrilloLog * contest_log ();
|
||||
Multiplier const * multiplier () const;
|
||||
FoxLog * fox_log ();
|
||||
|
||||
private:
|
||||
Configuration const * config_;
|
||||
WorkedBefore worked_before_;
|
||||
QScopedPointer<CabrilloLog> contest_log_;
|
||||
QScopedPointer<Multiplier> mutable multiplier_;
|
||||
QScopedPointer<FoxLog> fox_log_;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -2,10 +2,12 @@ SOURCES += \
|
||||
logbook/countriesworked.cpp \
|
||||
logbook/logbook.cpp \
|
||||
logbook/AD1CCty.cpp \
|
||||
logbook/WorkedBefore.cpp
|
||||
logbook/WorkedBefore.cpp \
|
||||
logbook/Multiplier.cpp
|
||||
|
||||
HEADERS += \
|
||||
logbook/WorkedBefore.hpp \
|
||||
logbook/logbook.h \
|
||||
logbook/countriesworked.h \
|
||||
logbook/AD1CCty.hpp
|
||||
logbook/AD1CCty.hpp \
|
||||
logbook/Multiplier.hpp
|
||||
|
2
main.cpp
2
main.cpp
@ -380,10 +380,12 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
MessageBox::critical_message (nullptr, QApplication::translate ("main", "Fatal error"), e.what ());
|
||||
std::cerr << "Error: " << e.what () << '\n';
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
MessageBox::critical_message (nullptr, QApplication::translate ("main", "Unexpected fatal error"));
|
||||
std::cerr << "Unexpected fatal error\n";
|
||||
throw; // hoping the runtime might tell us more about the exception
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <QDataStream>
|
||||
#include "Configuration.hpp"
|
||||
#include "Bands.hpp"
|
||||
#include "logbook/AD1CCty.hpp"
|
||||
#include "qt_db_helpers.hpp"
|
||||
#include "pimpl_impl.hpp"
|
||||
|
||||
@ -19,59 +20,109 @@ class CabrilloLog::impl final
|
||||
: public QSqlTableModel
|
||||
{
|
||||
public:
|
||||
impl (Configuration const *);
|
||||
impl (CabrilloLog *, Configuration const *);
|
||||
|
||||
QVariant data (QModelIndex const& index, int role) const
|
||||
int columnCount (QModelIndex const& /*index */) const override
|
||||
{
|
||||
auto value = QSqlTableModel::data (index, role);
|
||||
if (index.column () == fieldIndex ("when")
|
||||
&& (Qt::DisplayRole == role || Qt::EditRole == role))
|
||||
return QSqlTableModel::columnCount () + 1;
|
||||
}
|
||||
|
||||
Qt::ItemFlags flags (QModelIndex const& index) const override
|
||||
{
|
||||
auto flags = QSqlTableModel::flags (index);
|
||||
if (index.isValid () && index.column () == columnCount (index) - 1)
|
||||
{
|
||||
auto t = QDateTime::fromMSecsSinceEpoch (value.toULongLong () * 1000ull, Qt::UTC);
|
||||
flags = Qt::ItemIsEnabled;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
QVariant data (QModelIndex const& model_index, int role) const override
|
||||
{
|
||||
QVariant value;
|
||||
if (model_index.isValid () && model_index.column () == columnCount (model_index) - 1)
|
||||
{ // derive band column
|
||||
if (Qt::DisplayRole == role)
|
||||
{
|
||||
QLocale locale;
|
||||
return locale.toString (t, locale.dateFormat (QLocale::ShortFormat) + " hh:mm:ss");
|
||||
value = configuration_->bands ()->find (QSqlTableModel::data (index (model_index.row (), fieldIndex ("frequency"))).toULongLong ());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = QSqlTableModel::data (model_index, role);
|
||||
if (model_index.column () == fieldIndex ("frequency") && Qt::DisplayRole == role)
|
||||
{
|
||||
value = Radio::frequency_MHz_string (value.value<Radio::Frequency> (), 3); // kHz precision
|
||||
}
|
||||
else if (model_index.column () == fieldIndex ("when")
|
||||
&& (Qt::DisplayRole == role || Qt::EditRole == role))
|
||||
{ // adjust date/time to Qt format
|
||||
auto t = QDateTime::fromMSecsSinceEpoch (value.toULongLong () * 1000ull, Qt::UTC);
|
||||
if (Qt::DisplayRole == role)
|
||||
{
|
||||
QLocale locale;
|
||||
return locale.toString (t, locale.dateFormat (QLocale::ShortFormat) + " hh:mm:ss");
|
||||
}
|
||||
value = t;
|
||||
}
|
||||
value = t;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
QString cabrillo_frequency_string (Radio::Frequency frequency) const;
|
||||
void create_table ();
|
||||
|
||||
CabrilloLog * self_;
|
||||
Configuration const * configuration_;
|
||||
QSqlQuery mutable dupe_query_;
|
||||
QSqlQuery mutable export_query_;
|
||||
bool adding_row_;
|
||||
};
|
||||
|
||||
CabrilloLog::impl::impl (Configuration const * configuration)
|
||||
: QSqlTableModel {}
|
||||
CabrilloLog::impl::impl (CabrilloLog * self, Configuration const * configuration)
|
||||
: self_ {self}
|
||||
, configuration_ {configuration}
|
||||
, adding_row_ {false}
|
||||
{
|
||||
if (!database ().tables ().contains ("cabrillo_log"))
|
||||
if (!database ().tables ().contains ("cabrillo_log_v2"))
|
||||
{
|
||||
QSqlQuery query;
|
||||
SQL_error_check (query, static_cast<bool (QSqlQuery::*) (QString const&)> (&QSqlQuery::exec),
|
||||
"CREATE TABLE cabrillo_log ("
|
||||
" id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
|
||||
" frequency INTEGER NOT NULL,"
|
||||
" \"when\" DATETIME NOT NULL,"
|
||||
" call VARCHAR(20) NOT NULL,"
|
||||
" exchange_sent VARCHAR(32) NOT NULL,"
|
||||
" exchange_rcvd VARCHAR(32) NOT NULL,"
|
||||
" band VARCHAR(6) NOT NULL"
|
||||
")");
|
||||
create_table ();
|
||||
}
|
||||
|
||||
setEditStrategy (QSqlTableModel::OnFieldChange);
|
||||
setTable ("cabrillo_log_v2");
|
||||
setHeaderData (fieldIndex ("frequency"), Qt::Horizontal, tr ("Freq(MHz)"));
|
||||
setHeaderData (fieldIndex ("mode"), Qt::Horizontal, tr ("Mode"));
|
||||
setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)"));
|
||||
setHeaderData (fieldIndex ("call"), Qt::Horizontal, tr ("Call"));
|
||||
setHeaderData (fieldIndex ("exchange_sent"), Qt::Horizontal, tr ("Sent"));
|
||||
setHeaderData (fieldIndex ("exchange_rcvd"), Qt::Horizontal, tr ("Rcvd"));
|
||||
setHeaderData (columnCount (QModelIndex {}) - 1, Qt::Horizontal, tr ("Band"));
|
||||
|
||||
// This descending order by time is important, it makes the view
|
||||
// place the latest row at the top, without this the model/view
|
||||
// interactions are both sluggish and unhelpful.
|
||||
setSort (fieldIndex ("when"), Qt::DescendingOrder);
|
||||
|
||||
connect (this, &CabrilloLog::impl::modelReset, self_, &CabrilloLog::data_changed);
|
||||
connect (this, &CabrilloLog::impl::dataChanged, [this] (QModelIndex const& tl, QModelIndex const& br) {
|
||||
if (!adding_row_ && !(tl == br)) // ignore single cell changes
|
||||
// as a another change for the
|
||||
// whole row will follow
|
||||
{
|
||||
Q_EMIT self_->data_changed ();
|
||||
}
|
||||
});
|
||||
|
||||
SQL_error_check (*this, &QSqlTableModel::select);
|
||||
|
||||
SQL_error_check (dupe_query_, &QSqlQuery::prepare,
|
||||
"SELECT "
|
||||
" COUNT(*) "
|
||||
" frequency "
|
||||
" FROM "
|
||||
" cabrillo_log "
|
||||
" cabrillo_log_v2 "
|
||||
" WHERE "
|
||||
" call = :call "
|
||||
" AND band = :band");
|
||||
" call = :call ");
|
||||
|
||||
SQL_error_check (export_query_, &QSqlQuery::prepare,
|
||||
"SELECT "
|
||||
@ -81,32 +132,31 @@ CabrilloLog::impl::impl (Configuration const * configuration)
|
||||
" , call"
|
||||
" , exchange_rcvd"
|
||||
" FROM "
|
||||
" cabrillo_log "
|
||||
" cabrillo_log_v2 "
|
||||
" ORDER BY "
|
||||
" \"when\"");
|
||||
|
||||
setEditStrategy (QSqlTableModel::OnFieldChange);
|
||||
setTable ("cabrillo_log");
|
||||
setHeaderData (fieldIndex ("frequency"), Qt::Horizontal, tr ("Freq(kHz)"));
|
||||
setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)"));
|
||||
setHeaderData (fieldIndex ("call"), Qt::Horizontal, tr ("Call"));
|
||||
setHeaderData (fieldIndex ("exchange_sent"), Qt::Horizontal, tr ("Sent"));
|
||||
setHeaderData (fieldIndex ("exchange_rcvd"), Qt::Horizontal, tr ("Rcvd"));
|
||||
setHeaderData (fieldIndex ("band"), Qt::Horizontal, tr ("Band"));
|
||||
}
|
||||
|
||||
// This descending order by time is important, it makes the view
|
||||
// place the latest row at the top, without this the model/view
|
||||
// interactions are both sluggish and unhelpful.
|
||||
setSort (fieldIndex ("when"), Qt::DescendingOrder);
|
||||
|
||||
SQL_error_check (*this, &QSqlTableModel::select);
|
||||
void CabrilloLog::impl::create_table ()
|
||||
{
|
||||
QSqlQuery query;
|
||||
SQL_error_check (query, static_cast<bool (QSqlQuery::*) (QString const&)> (&QSqlQuery::exec),
|
||||
"CREATE TABLE cabrillo_log_v2 ("
|
||||
" id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,"
|
||||
" frequency INTEGER NOT NULL,"
|
||||
" mode VARCHAR(6) NOT NULL,"
|
||||
" \"when\" DATETIME NOT NULL,"
|
||||
" call VARCHAR(20) NOT NULL,"
|
||||
" exchange_sent VARCHAR(32) NOT NULL,"
|
||||
" exchange_rcvd VARCHAR(32) NOT NULL"
|
||||
")");
|
||||
}
|
||||
|
||||
// frequency here is in kHz
|
||||
QString CabrilloLog::impl::cabrillo_frequency_string (Radio::Frequency frequency) const
|
||||
{
|
||||
QString result;
|
||||
auto band = configuration_->bands ()->find (frequency * 1000ull);
|
||||
auto band = configuration_->bands ()->find (frequency);
|
||||
if ("1mm" == band) result = "LIGHT";
|
||||
else if ("2mm" == band) result = "241G";
|
||||
else if ("2.5mm" == band) result = "134G";
|
||||
@ -124,12 +174,15 @@ QString CabrilloLog::impl::cabrillo_frequency_string (Radio::Frequency frequency
|
||||
else if ("2m" == band) result = "144";
|
||||
else if ("4m" == band) result = "70";
|
||||
else if ("6m" == band) result = "50";
|
||||
else result = QString::number (frequency);
|
||||
else result = QString::number (frequency / 1000ull);
|
||||
return result;
|
||||
}
|
||||
|
||||
CabrilloLog::CabrilloLog (Configuration const * configuration)
|
||||
: m_ {configuration}
|
||||
#include "moc_CabrilloLog.cpp"
|
||||
|
||||
CabrilloLog::CabrilloLog (Configuration const * configuration, QObject * parent)
|
||||
: QObject {parent}
|
||||
, m_ {this, configuration}
|
||||
{
|
||||
Q_ASSERT (configuration);
|
||||
}
|
||||
@ -158,11 +211,12 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
bool CabrilloLog::add_QSO (Frequency frequency, QDateTime const& when, QString const& call
|
||||
bool CabrilloLog::add_QSO (Frequency frequency, QString const& mode, QDateTime const& when, QString const& call
|
||||
, QString const& exchange_sent, QString const& exchange_received)
|
||||
{
|
||||
auto record = m_->record ();
|
||||
record.setValue ("frequency", frequency / 1000ull); // kHz
|
||||
record.setValue ("frequency", frequency);
|
||||
record.setValue ("mode", mode);
|
||||
if (!when.isNull ())
|
||||
{
|
||||
record.setValue ("when", when.toMSecsSinceEpoch () / 1000ull);
|
||||
@ -174,15 +228,16 @@ bool CabrilloLog::add_QSO (Frequency frequency, QDateTime const& when, QString c
|
||||
set_value_maybe_null (record, "call", call);
|
||||
set_value_maybe_null (record, "exchange_sent", exchange_sent);
|
||||
set_value_maybe_null (record, "exchange_rcvd", exchange_received);
|
||||
set_value_maybe_null (record, "band", m_->configuration_->bands ()->find (frequency));
|
||||
if (m_->isDirty ())
|
||||
{
|
||||
m_->revert (); // discard any uncommitted changes
|
||||
}
|
||||
m_->setEditStrategy (QSqlTableModel::OnManualSubmit);
|
||||
ConditionalTransaction transaction {*m_};
|
||||
m_->adding_row_ = true;
|
||||
auto ok = m_->insertRecord (-1, record);
|
||||
transaction.submit ();
|
||||
m_->adding_row_ = false;
|
||||
m_->setEditStrategy (QSqlTableModel::OnFieldChange);
|
||||
return ok;
|
||||
}
|
||||
@ -190,10 +245,18 @@ bool CabrilloLog::add_QSO (Frequency frequency, QDateTime const& when, QString c
|
||||
bool CabrilloLog::dupe (Frequency frequency, QString const& call) const
|
||||
{
|
||||
m_->dupe_query_.bindValue (":call", call);
|
||||
m_->dupe_query_.bindValue (":band", m_->configuration_->bands ()->find (frequency));
|
||||
SQL_error_check (m_->dupe_query_, static_cast<bool (QSqlQuery::*) ()> (&QSqlQuery::exec));
|
||||
m_->dupe_query_.next ();
|
||||
return m_->dupe_query_.value (0).toInt ();
|
||||
auto record = m_->dupe_query_.record ();
|
||||
auto frequency_index = record.indexOf ("frequency");
|
||||
while (m_->dupe_query_.next ())
|
||||
{
|
||||
if (m_->configuration_->bands ()->find (m_->dupe_query_.value (frequency_index).toULongLong ())
|
||||
== m_->configuration_->bands ()->find (frequency))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CabrilloLog::reset ()
|
||||
@ -208,6 +271,7 @@ void CabrilloLog::reset ()
|
||||
transaction.submit ();
|
||||
m_->select (); // to refresh views
|
||||
m_->setEditStrategy (QSqlTableModel::OnFieldChange);
|
||||
Q_EMIT data_changed ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,6 +280,7 @@ void CabrilloLog::export_qsos (QTextStream& stream) const
|
||||
SQL_error_check (m_->export_query_, static_cast<bool (QSqlQuery::*) ()> (&QSqlQuery::exec));
|
||||
auto record = m_->export_query_.record ();
|
||||
auto frequency_index = record.indexOf ("frequency");
|
||||
// auto mode_index = record.indexOf ("mode");
|
||||
auto when_index = record.indexOf ("when");
|
||||
auto call_index = record.indexOf ("call");
|
||||
auto sent_index = record.indexOf ("exchange_sent");
|
||||
@ -232,3 +297,17 @@ void CabrilloLog::export_qsos (QTextStream& stream) const
|
||||
.arg (m_->export_query_.value (rcvd_index).toString (), -13);
|
||||
}
|
||||
}
|
||||
|
||||
auto CabrilloLog::unique_DXCC_entities (AD1CCty const * countries) const -> worked_set
|
||||
{
|
||||
QSqlQuery q {"SELECT DISTINCT BAND, CALL FROM cabrillo_log_v2"};
|
||||
auto band_index = q.record ().indexOf ("band");
|
||||
auto call_index = q.record ().indexOf ("call");
|
||||
worked_set entities;
|
||||
while (q.next ())
|
||||
{
|
||||
entities << worked_item {q.value (band_index).toString ()
|
||||
, countries->lookup (q.value (call_index).toString ()).primary_prefix};
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
@ -1,33 +1,43 @@
|
||||
#ifndef CABRILLO_LOG_HPP_
|
||||
#define CABRILLO_LOG_HPP_
|
||||
|
||||
#include <boost/core/noncopyable.hpp>
|
||||
#include <QObject>
|
||||
#include <QSet>
|
||||
#include <QPair>
|
||||
#include <QString>
|
||||
#include "Radio.hpp"
|
||||
#include "pimpl_h.hpp"
|
||||
|
||||
class Configuration;
|
||||
class QDateTime;
|
||||
class QString;
|
||||
class QSqlTableModel;
|
||||
class QTextStream;
|
||||
class AD1CCty;
|
||||
|
||||
class CabrilloLog final
|
||||
: private boost::noncopyable
|
||||
: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
using Frequency = Radio::Frequency;
|
||||
using worked_item = QPair<QString, QString>;
|
||||
using worked_set = QSet<worked_item>;
|
||||
|
||||
explicit CabrilloLog (Configuration const *);
|
||||
explicit CabrilloLog (Configuration const *, QObject * parent = nullptr);
|
||||
~CabrilloLog ();
|
||||
|
||||
// returns false if insert fails
|
||||
bool add_QSO (Frequency, QDateTime const&, QString const& call
|
||||
bool add_QSO (Frequency, QString const& mode, QDateTime const&, QString const& call
|
||||
, QString const& report_sent, QString const& report_received);
|
||||
bool dupe (Frequency, QString const& call) const;
|
||||
|
||||
QSqlTableModel * model ();
|
||||
void reset ();
|
||||
void export_qsos (QTextStream&) const;
|
||||
worked_set unique_DXCC_entities (AD1CCty const *) const;
|
||||
|
||||
Q_SIGNAL void data_changed () const;
|
||||
|
||||
private:
|
||||
class impl;
|
||||
|
@ -127,7 +127,9 @@ namespace
|
||||
{7074000, Modes::FT8, IARURegions::ALL},
|
||||
{7076000, Modes::JT65, IARURegions::ALL},
|
||||
{7078000, Modes::JT9, IARURegions::ALL},
|
||||
{7047000, Modes::FT4, IARURegions::ALL}, // provisional
|
||||
{7047500, Modes::FT4, IARURegions::ALL}, // provisional - moved
|
||||
// up 500Hz to clear
|
||||
// W1AW code practice QRG
|
||||
|
||||
// Band plans (all USB dial unless stated otherwise)
|
||||
//
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <QString>
|
||||
#include <QSqlError>
|
||||
#include <QSqlTableModel>
|
||||
#include "boost/core/noncopyable.hpp"
|
||||
|
||||
template<typename T, typename Func, typename... Args>
|
||||
void SQL_error_check (T&& object, Func func, Args&&... args)
|
||||
|
@ -1,5 +1,5 @@
|
||||
set (SAMPLE_FILES
|
||||
FT4/190106_000112.wav
|
||||
FT4/000000_000002.wav
|
||||
FT8/181201_180245.wav
|
||||
ISCAT/ISCAT-A/VK7MO_110401_235515.wav
|
||||
ISCAT/ISCAT-B/K0AWU_100714_115000.wav
|
||||
|
@ -1,10 +1,12 @@
|
||||
#include "CabrilloLogWindow.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <QApplication>
|
||||
#include <QIdentityProxyModel>
|
||||
#include <QSqlTableModel>
|
||||
#include "Configuration.hpp"
|
||||
#include "models/Bands.hpp"
|
||||
#include "item_delegates/FrequencyDelegate.hpp"
|
||||
#include "item_delegates/ForeignKeyDelegate.hpp"
|
||||
#include "item_delegates/CallsignDelegate.hpp"
|
||||
#include "pimpl_impl.hpp"
|
||||
@ -29,7 +31,7 @@ namespace
|
||||
switch (index.column ())
|
||||
{
|
||||
case 1:
|
||||
case 6:
|
||||
case 7:
|
||||
return Qt::AlignRight + Qt::AlignVCenter;
|
||||
default:
|
||||
break;
|
||||
@ -63,10 +65,10 @@ CabrilloLogWindow::CabrilloLogWindow (QSettings * settings, Configuration const
|
||||
m_->format_model_.setSourceModel (m_->log_model_);
|
||||
m_->ui_.log_table_view->setModel (&m_->format_model_);
|
||||
set_log_view (m_->ui_.log_table_view);
|
||||
m_->ui_.log_table_view->setItemDelegateForColumn (3, new CallsignDelegate {this});
|
||||
m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), 0, this});
|
||||
m_->ui_.log_table_view->setItemDelegateForColumn (1, new FrequencyDelegate {this});
|
||||
m_->ui_.log_table_view->setItemDelegateForColumn (4, new CallsignDelegate {this});
|
||||
auto h_header = m_->ui_.log_table_view->horizontalHeader ();
|
||||
h_header->moveSection (6, 1); // band to first column
|
||||
h_header->moveSection (7, 1); // band to first column
|
||||
}
|
||||
|
||||
CabrilloLogWindow::~CabrilloLogWindow ()
|
||||
|
54
widgets/FrequencyDeltaLineEdit.cpp
Normal file
54
widgets/FrequencyDeltaLineEdit.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include "FrequencyDeltaLineEdit.hpp"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <QDoubleValidator>
|
||||
#include <QString>
|
||||
#include <QLocale>
|
||||
|
||||
#include "moc_FrequencyDeltaLineEdit.cpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class MHzValidator
|
||||
: public QDoubleValidator
|
||||
{
|
||||
public:
|
||||
MHzValidator (double bottom, double top, QObject * parent = nullptr)
|
||||
: QDoubleValidator {bottom, top, 6, parent}
|
||||
{
|
||||
}
|
||||
|
||||
State validate (QString& input, int& pos) const override
|
||||
{
|
||||
State result = QDoubleValidator::validate (input, pos);
|
||||
if (Acceptable == result)
|
||||
{
|
||||
bool ok;
|
||||
(void)QLocale {}.toDouble (input, &ok);
|
||||
if (!ok)
|
||||
{
|
||||
result = Intermediate;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
FrequencyDeltaLineEdit::FrequencyDeltaLineEdit (QWidget * parent)
|
||||
: QLineEdit (parent)
|
||||
{
|
||||
setValidator (new MHzValidator {-std::numeric_limits<FrequencyDelta>::max () / 10.e6,
|
||||
std::numeric_limits<FrequencyDelta>::max () / 10.e6, this});
|
||||
}
|
||||
|
||||
auto FrequencyDeltaLineEdit::frequency_delta () const -> FrequencyDelta
|
||||
{
|
||||
return Radio::frequency_delta (text (), 6);
|
||||
}
|
||||
|
||||
void FrequencyDeltaLineEdit::frequency_delta (FrequencyDelta d)
|
||||
{
|
||||
setText (Radio::frequency_MHz_string (d));
|
||||
}
|
29
widgets/FrequencyDeltaLineEdit.hpp
Normal file
29
widgets/FrequencyDeltaLineEdit.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef FREQUENCY_DELTA_LINE_EDIT_HPP_
|
||||
#define FREQUENCY_DELTA_LINE_EDIT_HPP_
|
||||
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "Radio.hpp"
|
||||
|
||||
class QWidget;
|
||||
|
||||
//
|
||||
// MHz frequency delta line edit with validation
|
||||
//
|
||||
class FrequencyDeltaLineEdit final
|
||||
: public QLineEdit
|
||||
{
|
||||
Q_OBJECT;
|
||||
Q_PROPERTY (FrequencyDelta frequency_delta READ frequency_delta WRITE frequency_delta USER true);
|
||||
|
||||
public:
|
||||
using FrequencyDelta = Radio::FrequencyDelta;
|
||||
|
||||
explicit FrequencyDeltaLineEdit (QWidget * parent = nullptr);
|
||||
|
||||
// Property frequency_delta implementation
|
||||
FrequencyDelta frequency_delta () const;
|
||||
void frequency_delta (FrequencyDelta);
|
||||
};
|
||||
|
||||
#endif
|
@ -51,21 +51,3 @@ void FrequencyLineEdit::frequency (Frequency f)
|
||||
{
|
||||
setText (Radio::frequency_MHz_string (f));
|
||||
}
|
||||
|
||||
|
||||
FrequencyDeltaLineEdit::FrequencyDeltaLineEdit (QWidget * parent)
|
||||
: QLineEdit (parent)
|
||||
{
|
||||
setValidator (new MHzValidator {-std::numeric_limits<FrequencyDelta>::max () / 10.e6,
|
||||
std::numeric_limits<FrequencyDelta>::max () / 10.e6, this});
|
||||
}
|
||||
|
||||
auto FrequencyDeltaLineEdit::frequency_delta () const -> FrequencyDelta
|
||||
{
|
||||
return Radio::frequency_delta (text (), 6);
|
||||
}
|
||||
|
||||
void FrequencyDeltaLineEdit::frequency_delta (FrequencyDelta d)
|
||||
{
|
||||
setText (Radio::frequency_MHz_string (d));
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
class QWidget;
|
||||
|
||||
//
|
||||
// MHz frequency line edits with validation
|
||||
// MHz frequency line edit with validation
|
||||
//
|
||||
class FrequencyLineEdit final
|
||||
: public QLineEdit
|
||||
@ -26,20 +26,4 @@ public:
|
||||
void frequency (Frequency);
|
||||
};
|
||||
|
||||
class FrequencyDeltaLineEdit final
|
||||
: public QLineEdit
|
||||
{
|
||||
Q_OBJECT;
|
||||
Q_PROPERTY (FrequencyDelta frequency_delta READ frequency_delta WRITE frequency_delta USER true);
|
||||
|
||||
public:
|
||||
using FrequencyDelta = Radio::FrequencyDelta;
|
||||
|
||||
explicit FrequencyDeltaLineEdit (QWidget * parent = nullptr);
|
||||
|
||||
// Property frequency_delta implementation
|
||||
FrequencyDelta frequency_delta () const;
|
||||
void frequency_delta (FrequencyDelta);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -271,7 +271,7 @@ QString DisplayText::appendWorkedB4 (QString message, QString call, QString cons
|
||||
if(call.length()<3) return message;
|
||||
if(!call.contains(QRegExp("[0-9]|[A-Z]"))) return message;
|
||||
|
||||
auto const& looked_up = logBook.countries ().lookup (call);
|
||||
auto const& looked_up = logBook.countries ()->lookup (call);
|
||||
logBook.match (call, currentMode, grid, looked_up, callB4, countryB4, gridB4, continentB4, CQZoneB4, ITUZoneB4);
|
||||
logBook.match (call, currentMode, grid, looked_up, callB4onBand, countryB4onBand, gridB4onBand,
|
||||
continentB4onBand, CQZoneB4onBand, ITUZoneB4onBand, currentBand);
|
||||
|
@ -65,6 +65,4 @@ private:
|
||||
int modified_vertical_scrollbar_max_;
|
||||
};
|
||||
|
||||
extern QHash<QString,int> m_LoTW;
|
||||
|
||||
#endif // DISPLAYTEXT_H
|
||||
|
@ -16,11 +16,12 @@
|
||||
#include "moc_logqso.cpp"
|
||||
|
||||
LogQSO::LogQSO(QString const& programTitle, QSettings * settings
|
||||
, Configuration const * config, QWidget *parent)
|
||||
, Configuration const * config, LogBook * log, QWidget *parent)
|
||||
: QDialog {parent, Qt::WindowStaysOnTopHint | Qt::WindowTitleHint | Qt::WindowSystemMenuHint}
|
||||
, ui(new Ui::LogQSO)
|
||||
, m_settings (settings)
|
||||
, m_config {config}
|
||||
, m_log {log}
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowTitle(programTitle + " - Log QSO");
|
||||
@ -57,8 +58,7 @@ void LogQSO::storeSettings () const
|
||||
void LogQSO::initLogQSO(QString const& hisCall, QString const& hisGrid, QString mode,
|
||||
QString const& rptSent, QString const& rptRcvd,
|
||||
QDateTime const& dateTimeOn, QDateTime const& dateTimeOff,
|
||||
Radio::Frequency dialFreq, bool noSuffix, QString xSent, QString xRcvd,
|
||||
CabrilloLog * cabrillo_log)
|
||||
Radio::Frequency dialFreq, bool noSuffix, QString xSent, QString xRcvd)
|
||||
{
|
||||
if(!isHidden()) return;
|
||||
ui->call->setText (hisCall);
|
||||
@ -100,7 +100,6 @@ void LogQSO::initLogQSO(QString const& hisCall, QString const& hisGrid, QString
|
||||
ui->loggedOperator->setText(m_config->opCall());
|
||||
ui->exchSent->setText (xSent);
|
||||
ui->exchRcvd->setText (xRcvd);
|
||||
m_cabrilloLog = cabrillo_log;
|
||||
|
||||
using SpOp = Configuration::SpecialOperatingActivity;
|
||||
auto special_op = m_config->special_op_id ();
|
||||
@ -158,7 +157,7 @@ void LogQSO::accept()
|
||||
return; // without accepting
|
||||
}
|
||||
|
||||
if (!m_cabrilloLog->add_QSO (m_dialFreq, dateTimeOff, hisCall, xsent, xrcvd))
|
||||
if (!m_log->contest_log ()->add_QSO (m_dialFreq, mode, dateTimeOff, hisCall, xsent, xrcvd))
|
||||
{
|
||||
show ();
|
||||
MessageBox::warning_message (this, tr ("Invalid QSO Data"),
|
||||
|
@ -17,19 +17,19 @@ namespace Ui {
|
||||
class QSettings;
|
||||
class Configuration;
|
||||
class QByteArray;
|
||||
class CabrilloLog;
|
||||
class LogBook;
|
||||
|
||||
class LogQSO : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LogQSO(QString const& programTitle, QSettings *, Configuration const *, QWidget *parent = 0);
|
||||
explicit LogQSO(QString const& programTitle, QSettings *, Configuration const *, LogBook *, QWidget *parent = 0);
|
||||
~LogQSO();
|
||||
void initLogQSO(QString const& hisCall, QString const& hisGrid, QString mode,
|
||||
QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn,
|
||||
QDateTime const& dateTimeOff, Radio::Frequency dialFreq,
|
||||
bool noSuffix, QString xSent, QString xRcvd, CabrilloLog *);
|
||||
bool noSuffix, QString xSent, QString xRcvd);
|
||||
|
||||
public slots:
|
||||
void accept();
|
||||
@ -54,12 +54,12 @@ private:
|
||||
QScopedPointer<Ui::LogQSO> ui;
|
||||
QSettings * m_settings;
|
||||
Configuration const * m_config;
|
||||
LogBook * m_log;
|
||||
QString m_txPower;
|
||||
QString m_comments;
|
||||
Radio::Frequency m_dialFreq;
|
||||
QString m_myCall;
|
||||
QString m_myGrid;
|
||||
CabrilloLog * m_cabrilloLog;
|
||||
};
|
||||
|
||||
#endif // LogQSO_H
|
||||
|
@ -244,7 +244,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
|
||||
m_echoGraph (new EchoGraph(m_settings)),
|
||||
m_fastGraph (new FastGraph(m_settings)),
|
||||
// no parent so that it has a taskbar icon
|
||||
m_logDlg (new LogQSO (program_title (), m_settings, &m_config, nullptr)),
|
||||
m_logDlg (new LogQSO (program_title (), m_settings, &m_config, &m_logBook, nullptr)),
|
||||
m_lastDialFreq {0},
|
||||
m_dialFreqRxWSPR {0},
|
||||
m_detector {new Detector {RX_SAMPLE_RATE, double(NTMAX), downSampleFactor}},
|
||||
@ -2544,16 +2544,14 @@ void MainWindow::on_actionAstronomical_data_toggled (bool checked)
|
||||
|
||||
void MainWindow::on_fox_log_action_triggered()
|
||||
{
|
||||
if (!m_foxLog) m_foxLog.reset (new FoxLog {&m_config});
|
||||
if (!m_foxLogWindow)
|
||||
{
|
||||
m_foxLogWindow.reset (new FoxLogWindow {m_settings, &m_config, m_foxLog.data ()});
|
||||
m_foxLogWindow.reset (new FoxLogWindow {m_settings, &m_config, m_logBook.fox_log ()});
|
||||
|
||||
// Connect signals from fox log window
|
||||
connect (this, &MainWindow::finished, m_foxLogWindow.data (), &FoxLogWindow::close);
|
||||
connect (m_foxLogWindow.data (), &FoxLogWindow::reset_log_model, [this] () {
|
||||
if (!m_foxLog) m_foxLog.reset (new FoxLog {&m_config});
|
||||
m_foxLog->reset ();
|
||||
m_logBook.fox_log ()->reset ();
|
||||
});
|
||||
}
|
||||
m_foxLogWindow->showNormal ();
|
||||
@ -2563,10 +2561,9 @@ void MainWindow::on_fox_log_action_triggered()
|
||||
|
||||
void MainWindow::on_contest_log_action_triggered()
|
||||
{
|
||||
if (!m_cabrilloLog) m_cabrilloLog.reset (new CabrilloLog {&m_config});
|
||||
if (!m_contestLogWindow)
|
||||
{
|
||||
m_contestLogWindow.reset (new CabrilloLogWindow {m_settings, &m_config, m_cabrilloLog->model ()});
|
||||
m_contestLogWindow.reset (new CabrilloLogWindow {m_settings, &m_config, m_logBook.contest_log ()->model ()});
|
||||
|
||||
// Connect signals from contest log window
|
||||
connect (this, &MainWindow::finished, m_contestLogWindow.data (), &CabrilloLogWindow::close);
|
||||
@ -5521,15 +5518,9 @@ void MainWindow::on_logQSOButton_clicked() //Log QSO button
|
||||
default: break;
|
||||
}
|
||||
|
||||
auto special_op = m_config.special_op_id ();
|
||||
if (SpecOp::NONE < special_op && special_op < SpecOp::FOX)
|
||||
{
|
||||
if (!m_cabrilloLog) m_cabrilloLog.reset (new CabrilloLog {&m_config});
|
||||
}
|
||||
m_logDlg->initLogQSO (m_hisCall, grid, m_modeTx, m_rptSent, m_rptRcvd,
|
||||
m_dateTimeQSOOn, dateTimeQSOOff, m_freqNominal +
|
||||
ui->TxFreqSpinBox->value(), m_noSuffix, m_xSent, m_xRcvd,
|
||||
m_cabrilloLog.data ());
|
||||
ui->TxFreqSpinBox->value(), m_noSuffix, m_xSent, m_xRcvd);
|
||||
m_inQSOwith="";
|
||||
}
|
||||
|
||||
@ -6369,15 +6360,13 @@ void MainWindow::on_reset_cabrillo_log_action_triggered ()
|
||||
"for export in your Cabrillo log.")))
|
||||
{
|
||||
if(m_config.RTTY_Exchange()!="SCC") ui->sbSerialNumber->setValue(1);
|
||||
if (!m_cabrilloLog) m_cabrilloLog.reset (new CabrilloLog {&m_config});
|
||||
m_cabrilloLog->reset ();
|
||||
m_logBook.contest_log ()->reset ();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionExport_Cabrillo_log_triggered()
|
||||
{
|
||||
if (!m_cabrilloLog) m_cabrilloLog.reset (new CabrilloLog {&m_config});
|
||||
if (QDialog::Accepted == ExportCabrillo {m_settings, &m_config, m_cabrilloLog.data ()}.exec())
|
||||
if (QDialog::Accepted == ExportCabrillo {m_settings, &m_config, m_logBook.contest_log ()}.exec())
|
||||
{
|
||||
MessageBox::information_message (this, tr ("Cabrillo Log saved"));
|
||||
}
|
||||
@ -8278,7 +8267,7 @@ void MainWindow::houndCallers()
|
||||
if(!ui->textBrowser4->toPlainText().contains(paddedHoundCall)) {
|
||||
if(m_loggedByFox[houndCall].contains(m_lastBand)) continue; //already logged on this band
|
||||
if(m_foxQSO.contains(houndCall)) continue; //still in the QSO map
|
||||
auto const& entity = m_logBook.countries ().lookup (houndCall);
|
||||
auto const& entity = m_logBook.countries ()->lookup (houndCall);
|
||||
auto const& continent = AD1CCty::continent (entity.continent);
|
||||
|
||||
//If we are using a directed CQ, ignore Hound calls that do not comply.
|
||||
@ -8459,9 +8448,8 @@ list2Done:
|
||||
m_hisGrid=m_foxQSO[hc1].grid;
|
||||
m_rptSent=m_foxQSO[hc1].sent;
|
||||
m_rptRcvd=m_foxQSO[hc1].rcvd;
|
||||
if (!m_foxLog) m_foxLog.reset (new FoxLog {&m_config});
|
||||
if (!m_foxLogWindow) on_fox_log_action_triggered ();
|
||||
if (m_foxLog->add_QSO (QSO_time, m_hisCall, m_hisGrid, m_rptSent, m_rptRcvd, m_lastBand))
|
||||
if (m_logBook.fox_log ()->add_QSO (QSO_time, m_hisCall, m_hisGrid, m_rptSent, m_rptRcvd, m_lastBand))
|
||||
{
|
||||
writeFoxQSO (QString {" Log: %1 %2 %3 %4 %5"}.arg (m_hisCall).arg (m_hisGrid)
|
||||
.arg (m_rptSent).arg (m_rptRcvd).arg (m_lastBand));
|
||||
|
@ -72,9 +72,7 @@ class WideGraph;
|
||||
class LogQSO;
|
||||
class Transceiver;
|
||||
class MessageAveraging;
|
||||
class FoxLog;
|
||||
class FoxLogWindow;
|
||||
class CabrilloLog;
|
||||
class CabrilloLogWindow;
|
||||
class ColorHighlighting;
|
||||
class MessageClient;
|
||||
@ -376,9 +374,7 @@ private:
|
||||
QScopedPointer<HelpTextWindow> m_prefixes;
|
||||
QScopedPointer<HelpTextWindow> m_mouseCmnds;
|
||||
QScopedPointer<MessageAveraging> m_msgAvgWidget;
|
||||
QScopedPointer<FoxLog> m_foxLog;
|
||||
QScopedPointer<FoxLogWindow> m_foxLogWindow;
|
||||
QScopedPointer<CabrilloLog> m_cabrilloLog;
|
||||
QScopedPointer<CabrilloLogWindow> m_contestLogWindow;
|
||||
QScopedPointer<ColorHighlighting> m_colorHighlighting;
|
||||
Transceiver::TransceiverState m_rigState;
|
||||
|
@ -8,13 +8,14 @@ SOURCES += \
|
||||
widgets/fastplot.cpp widgets/MessageBox.cpp \
|
||||
widgets/colorhighlighting.cpp widgets/ExportCabrillo.cpp \
|
||||
widgets/AbstractLogWindow.cpp \
|
||||
widgets/FrequencyLineEdit.cpp widgets/FrequencyDeltaLineEdit.cpp \
|
||||
widgets/FoxLogWindow.cpp widgets/CabrilloLogWindow.cpp
|
||||
|
||||
HEADERS += \
|
||||
widgets/mainwindow.h widgets/plotter.h \
|
||||
widgets/about.h widgets/widegraph.h \
|
||||
widgets/displaytext.h widgets/logqso.h widgets/LettersSpinBox.hpp \
|
||||
widgets/FrequencyLineEdit.hpp widgets/signalmeter.h \
|
||||
widgets/FrequencyLineEdit.hpp widgets/FrequencyDeltaLineEdit.hpp widgets/signalmeter.h \
|
||||
widgets/meterwidget.h widgets/messageaveraging.h \
|
||||
widgets/echoplot.h widgets/echograph.h widgets/fastgraph.h \
|
||||
widgets/fastplot.h widgets/MessageBox.hpp widgets/colorhighlighting.h \
|
||||
|
Loading…
Reference in New Issue
Block a user