Merge tag 'wsjtx-2.0.0-rc3' into develop

Tagging the WSJT-X v2.0.0-rc3 release
This commit is contained in:
Bill Somerville 2018-10-17 01:04:00 +01:00
commit e3f4efefe6
59 changed files with 3583 additions and 123188 deletions

View File

@ -262,6 +262,9 @@ set (wsjt_qt_CXXSRCS
EqualizationToolsDialog.cpp EqualizationToolsDialog.cpp
DoubleClickablePushButton.cpp DoubleClickablePushButton.cpp
DoubleClickableRadioButton.cpp DoubleClickableRadioButton.cpp
LotWUsers.cpp
DecodeHighlightingModel.cpp
DecodeHighlightingListView.cpp
) )
set (wsjt_qtmm_CXXSRCS set (wsjt_qtmm_CXXSRCS
@ -1430,7 +1433,6 @@ install (FILES
install (FILES install (FILES
contrib/Ephemeris/JPLEPH contrib/Ephemeris/JPLEPH
contrib/lotw-user-activity.csv
DESTINATION ${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}
#COMPONENT runtime #COMPONENT runtime
) )

View File

@ -157,7 +157,6 @@
#include <QStandardPaths> #include <QStandardPaths>
#include <QFont> #include <QFont>
#include <QFontDialog> #include <QFontDialog>
#include <QColorDialog>
#include <QSerialPortInfo> #include <QSerialPortInfo>
#include <QScopedPointer> #include <QScopedPointer>
#include <QDebug> #include <QDebug>
@ -180,7 +179,9 @@
#include "MessageBox.hpp" #include "MessageBox.hpp"
#include "MaidenheadLocatorValidator.hpp" #include "MaidenheadLocatorValidator.hpp"
#include "CallsignValidator.hpp" #include "CallsignValidator.hpp"
#include "LotWUsers.hpp"
#include "ExchangeValidator.hpp" #include "ExchangeValidator.hpp"
#include "DecodeHighlightingModel.hpp"
#include "ui_Configuration.h" #include "ui_Configuration.h"
#include "moc_Configuration.cpp" #include "moc_Configuration.cpp"
@ -355,8 +356,11 @@ public:
using FrequencyDelta = Radio::FrequencyDelta; using FrequencyDelta = Radio::FrequencyDelta;
using port_type = Configuration::port_type; using port_type = Configuration::port_type;
explicit impl (Configuration * self, QDir const& temp_directory, explicit impl (Configuration * self
QSettings * settings, QWidget * parent); , QNetworkAccessManager * network_manager
, QDir const& temp_directory
, QSettings * settings
, QWidget * parent);
~impl (); ~impl ();
bool have_rig (); bool have_rig ();
@ -441,17 +445,8 @@ private:
Q_SLOT void on_calibration_slope_ppm_spin_box_valueChanged (double); Q_SLOT void on_calibration_slope_ppm_spin_box_valueChanged (double);
Q_SLOT void handle_transceiver_update (TransceiverState const&, unsigned sequence_number); Q_SLOT void handle_transceiver_update (TransceiverState const&, unsigned sequence_number);
Q_SLOT void handle_transceiver_failure (QString const& reason); Q_SLOT void handle_transceiver_failure (QString const& reason);
Q_SLOT void on_pbCQmsg_clicked(); Q_SLOT void on_reset_highlighting_to_defaults_push_button_clicked (bool);
Q_SLOT void on_pbMyCall_clicked(); Q_SLOT void on_LotW_CSV_fetch_push_button_clicked (bool);
Q_SLOT void on_pbTxMsg_clicked();
Q_SLOT void on_pbNewDXCC_clicked();
Q_SLOT void on_pbNewDXCCband_clicked();
Q_SLOT void on_pbNewCall_clicked();
Q_SLOT void on_pbNewCallBand_clicked();
Q_SLOT void on_pbNewGrid_clicked();
Q_SLOT void on_pbNewGridBand_clicked();
Q_SLOT void on_pbLoTW_clicked();
Q_SLOT void on_pbResetDefaults_clicked();
Q_SLOT void on_cbFox_clicked (bool); Q_SLOT void on_cbFox_clicked (bool);
Q_SLOT void on_cbHound_clicked (bool); Q_SLOT void on_cbHound_clicked (bool);
Q_SLOT void on_cbx2ToneSpacing_clicked(bool); Q_SLOT void on_cbx2ToneSpacing_clicked(bool);
@ -478,6 +473,7 @@ private:
QScopedPointer<Ui::configuration_dialog> ui_; QScopedPointer<Ui::configuration_dialog> ui_;
QNetworkAccessManager * network_manager_;
QSettings * settings_; QSettings * settings_;
QDir doc_dir_; QDir doc_dir_;
@ -495,6 +491,8 @@ private:
QFont decoded_text_font_; QFont decoded_text_font_;
QFont next_decoded_text_font_; QFont next_decoded_text_font_;
LotWUsers lotw_users_;
bool restart_sound_input_device_; bool restart_sound_input_device_;
bool restart_sound_output_device_; bool restart_sound_output_device_;
@ -523,10 +521,14 @@ private:
QAction * reset_frequencies_action_; QAction * reset_frequencies_action_;
FrequencyDialog * frequency_dialog_; FrequencyDialog * frequency_dialog_;
QAction * station_delete_action_; QAction station_delete_action_;
QAction * station_insert_action_; QAction station_insert_action_;
StationDialog * station_dialog_; StationDialog * station_dialog_;
DecodeHighlightingModel decode_highlighing_model_;
DecodeHighlightingModel next_decode_highlighing_model_;
int LotW_days_since_upload_;
TransceiverFactory::ParameterPack rig_params_; TransceiverFactory::ParameterPack rig_params_;
TransceiverFactory::ParameterPack saved_rig_params_; TransceiverFactory::ParameterPack saved_rig_params_;
TransceiverFactory::Capabilities::PortType last_port_type_; TransceiverFactory::Capabilities::PortType last_port_type_;
@ -546,26 +548,6 @@ private:
QString my_grid_; QString my_grid_;
QString FD_exchange_; QString FD_exchange_;
QString RTTY_exchange_; QString RTTY_exchange_;
QColor color_CQ_;
QColor next_color_CQ_;
QColor color_MyCall_;
QColor next_color_MyCall_;
QColor color_TxMsg_;
QColor next_color_TxMsg_;
QColor color_DXCC_;
QColor next_color_DXCC_;
QColor color_DXCCband_;
QColor next_color_DXCCband_;
QColor color_NewCall_;
QColor next_color_NewCall_;
QColor color_NewCallBand_;
QColor next_color_NewCallBand_;
QColor color_NewGrid_;
QColor next_color_NewGrid_;
QColor color_NewGridBand_;
QColor next_color_NewGridBand_;
QColor color_LoTW_;
QColor next_color_LoTW_;
qint32 id_interval_; qint32 id_interval_;
qint32 ntrials_; qint32 ntrials_;
@ -610,13 +592,9 @@ private:
QString opCall_; QString opCall_;
QString udp_server_name_; QString udp_server_name_;
port_type udp_server_port_; port_type udp_server_port_;
// QString n1mm_server_name () const;
QString n1mm_server_name_; QString n1mm_server_name_;
port_type n1mm_server_port_; port_type n1mm_server_port_;
bool broadcast_to_n1mm_; bool broadcast_to_n1mm_;
// port_type n1mm_server_port () const;
// bool valid_n1mm_info () const;
// bool broadcast_to_n1mm() const;
bool accept_udp_requests_; bool accept_udp_requests_;
bool udpWindowToFront_; bool udpWindowToFront_;
bool udpWindowRestore_; bool udpWindowRestore_;
@ -638,9 +616,9 @@ private:
// delegate to implementation class // delegate to implementation class
Configuration::Configuration (QDir const& temp_directory, Configuration::Configuration (QNetworkAccessManager * network_manager, QDir const& temp_directory,
QSettings * settings, QWidget * parent) QSettings * settings, QWidget * parent)
: m_ {this, temp_directory, settings, parent} : m_ {this, network_manager, temp_directory, settings, parent}
{ {
} }
@ -665,16 +643,6 @@ bool Configuration::restart_audio_input () const {return m_->restart_sound_input
bool Configuration::restart_audio_output () const {return m_->restart_sound_output_device_;} bool Configuration::restart_audio_output () const {return m_->restart_sound_output_device_;}
auto Configuration::type_2_msg_gen () const -> Type2MsgGen {return m_->type_2_msg_gen_;} auto Configuration::type_2_msg_gen () const -> Type2MsgGen {return m_->type_2_msg_gen_;}
QString Configuration::my_callsign () const {return m_->my_callsign_;} QString Configuration::my_callsign () const {return m_->my_callsign_;}
QColor Configuration::color_CQ () const {return m_->color_CQ_;}
QColor Configuration::color_MyCall () const {return m_->color_MyCall_;}
QColor Configuration::color_TxMsg () const {return m_->color_TxMsg_;}
QColor Configuration::color_DXCC () const {return m_->color_DXCC_;}
QColor Configuration::color_DXCCband() const {return m_->color_DXCCband_;}
QColor Configuration::color_NewCall () const {return m_->color_NewCall_;}
QColor Configuration::color_NewCallBand () const {return m_->color_NewCallBand_;}
QColor Configuration::color_NewGrid () const {return m_->color_NewGrid_;}
QColor Configuration::color_NewGridBand () const {return m_->color_NewGridBand_;}
QColor Configuration::color_LoTW() const {return m_->color_LoTW_;}
QFont Configuration::text_font () const {return m_->font_;} QFont Configuration::text_font () const {return m_->font_;}
QFont Configuration::decoded_text_font () const {return m_->decoded_text_font_;} QFont Configuration::decoded_text_font () const {return m_->decoded_text_font_;}
qint32 Configuration::id_interval () const {return m_->id_interval_;} qint32 Configuration::id_interval () const {return m_->id_interval_;}
@ -744,6 +712,8 @@ QDir Configuration::azel_directory () const {return m_->azel_directory_;}
QString Configuration::rig_name () const {return m_->rig_params_.rig_name;} QString Configuration::rig_name () const {return m_->rig_params_.rig_name;}
bool Configuration::pwrBandTxMemory () const {return m_->pwrBandTxMemory_;} bool Configuration::pwrBandTxMemory () const {return m_->pwrBandTxMemory_;}
bool Configuration::pwrBandTuneMemory () const {return m_->pwrBandTuneMemory_;} 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_;}
void Configuration::set_calibration (CalibrationParams params) void Configuration::set_calibration (CalibrationParams params)
{ {
@ -915,17 +885,19 @@ namespace
} }
} }
Configuration::impl::impl (Configuration * self, QDir const& temp_directory, Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network_manager
QSettings * settings, QWidget * parent) , QDir const& temp_directory, QSettings * settings, QWidget * parent)
: QDialog {parent} : QDialog {parent}
, self_ {self} , self_ {self}
, transceiver_thread_ {nullptr} , transceiver_thread_ {nullptr}
, ui_ {new Ui::configuration_dialog} , ui_ {new Ui::configuration_dialog}
, network_manager_ {network_manager}
, settings_ {settings} , settings_ {settings}
, doc_dir_ {doc_path ()} , doc_dir_ {doc_path ()}
, data_dir_ {data_path ()} , data_dir_ {data_path ()}
, temp_dir_ {temp_directory} , temp_dir_ {temp_directory}
, writeable_data_dir_ {QStandardPaths::writableLocation (QStandardPaths::DataLocation)} , writeable_data_dir_ {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}
, lotw_users_ {network_manager_}
, restart_sound_input_device_ {false} , restart_sound_input_device_ {false}
, restart_sound_output_device_ {false} , restart_sound_output_device_ {false}
, frequencies_ {&bands_} , frequencies_ {&bands_}
@ -935,7 +907,10 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
, current_offset_ {0} , current_offset_ {0}
, current_tx_offset_ {0} , current_tx_offset_ {0}
, frequency_dialog_ {new FrequencyDialog {&regions_, &modes_, this}} , frequency_dialog_ {new FrequencyDialog {&regions_, &modes_, this}}
, station_delete_action_ {tr ("&Delete"), nullptr}
, station_insert_action_ {tr ("&Insert ..."), nullptr}
, station_dialog_ {new StationDialog {&next_stations_, &bands_, this}} , station_dialog_ {new StationDialog {&next_stations_, &bands_, this}}
, LotW_days_since_upload_ {0}
, last_port_type_ {TransceiverFactory::Capabilities::none} , last_port_type_ {TransceiverFactory::Capabilities::none}
, rig_is_dummy_ {false} , rig_is_dummy_ {false}
, rig_active_ {false} , rig_active_ {false}
@ -1006,6 +981,15 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
// this must be done after the default paths above are set // this must be done after the default paths above are set
read_settings (); read_settings ();
// conditionally load LotW users data
ui_->LotW_CSV_fetch_push_button->setEnabled (false);
connect (&lotw_users_, &LotWUsers::load_finished, [this] () {
ui_->LotW_CSV_fetch_push_button->setEnabled (true);
});
lotw_users_.set_local_file_path (writeable_data_dir_.absoluteFilePath ("lotw-user-activity.csv"));
lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text ());
//
// validation // validation
ui_->callsign_line_edit->setValidator (new CallsignValidator {this}); ui_->callsign_line_edit->setValidator (new CallsignValidator {this});
ui_->grid_line_edit->setValidator (new MaidenheadLocatorValidator {this}); ui_->grid_line_edit->setValidator (new MaidenheadLocatorValidator {this});
@ -1124,29 +1108,30 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
ui_->frequencies_table_view->insertAction (nullptr, reset_frequencies_action_); ui_->frequencies_table_view->insertAction (nullptr, reset_frequencies_action_);
connect (reset_frequencies_action_, &QAction::triggered, this, &Configuration::impl::reset_frequencies); connect (reset_frequencies_action_, &QAction::triggered, this, &Configuration::impl::reset_frequencies);
// //
// setup stations table model & view // setup stations table model & view
// //
stations_.sort (StationList::band_column); stations_.sort (StationList::band_column);
ui_->stations_table_view->setModel (&next_stations_); ui_->stations_table_view->setModel (&next_stations_);
ui_->stations_table_view->sortByColumn (StationList::band_column, Qt::AscendingOrder); ui_->stations_table_view->sortByColumn (StationList::band_column, Qt::AscendingOrder);
// delegates // stations delegates
auto stations_item_delegate = new QStyledItemDelegate {this}; auto stations_item_delegate = new QStyledItemDelegate {this};
stations_item_delegate->setItemEditorFactory (item_editor_factory ()); stations_item_delegate->setItemEditorFactory (item_editor_factory ());
ui_->stations_table_view->setItemDelegate (stations_item_delegate); ui_->stations_table_view->setItemDelegate (stations_item_delegate);
ui_->stations_table_view->setItemDelegateForColumn (StationList::band_column, new ForeignKeyDelegate {&bands_, &next_stations_, 0, StationList::band_column, this}); ui_->stations_table_view->setItemDelegateForColumn (StationList::band_column, new ForeignKeyDelegate {&bands_, &next_stations_, 0, StationList::band_column, this});
// actions // stations actions
station_delete_action_ = new QAction {tr ("&Delete"), ui_->stations_table_view}; ui_->stations_table_view->addAction (&station_delete_action_);
ui_->stations_table_view->insertAction (nullptr, station_delete_action_); connect (&station_delete_action_, &QAction::triggered, this, &Configuration::impl::delete_stations);
connect (station_delete_action_, &QAction::triggered, this, &Configuration::impl::delete_stations);
station_insert_action_ = new QAction {tr ("&Insert ..."), ui_->stations_table_view}; ui_->stations_table_view->addAction (&station_insert_action_);
ui_->stations_table_view->insertAction (nullptr, station_insert_action_); connect (&station_insert_action_, &QAction::triggered, this, &Configuration::impl::insert_station);
connect (station_insert_action_, &QAction::triggered, this, &Configuration::impl::insert_station);
//
// colours and highlighting setup
//
ui_->highlighting_list_view->setModel (&next_decode_highlighing_model_);
// //
// load combo boxes with audio setup choices // load combo boxes with audio setup choices
@ -1190,16 +1175,6 @@ void Configuration::impl::initialize_models ()
ui_->callsign_line_edit->setText (my_callsign_); ui_->callsign_line_edit->setText (my_callsign_);
ui_->grid_line_edit->setText (my_grid_); ui_->grid_line_edit->setText (my_grid_);
ui_->use_dynamic_grid->setChecked(use_dynamic_grid_); ui_->use_dynamic_grid->setChecked(use_dynamic_grid_);
ui_->labCQ->setStyleSheet(QString("background: %1").arg(color_CQ_.name()));
ui_->labMyCall->setStyleSheet(QString("background: %1").arg(color_MyCall_.name()));
ui_->labTx->setStyleSheet(QString("background: %1").arg(color_TxMsg_.name()));
ui_->labDXCC->setStyleSheet(QString("background: %1").arg(color_DXCC_.name()));
ui_->labDXCCband->setStyleSheet(QString("background: %1").arg(color_DXCCband_.name()));
ui_->labNewCall->setStyleSheet(QString("background: %1").arg(color_NewCall_.name()));
ui_->labNewCallBand->setStyleSheet(QString("background: %1").arg(color_NewCallBand_.name()));
ui_->labNewGrid->setStyleSheet(QString("background: %1").arg(color_NewGrid_.name()));
ui_->labNewGridBand->setStyleSheet(QString("background: %1").arg(color_NewGridBand_.name()));
ui_->labLoTW->setStyleSheet(QString("color: %1").arg(color_LoTW_.name()));
ui_->CW_id_interval_spin_box->setValue (id_interval_); ui_->CW_id_interval_spin_box->setValue (id_interval_);
ui_->sbNtrials->setValue (ntrials_); ui_->sbNtrials->setValue (ntrials_);
ui_->sbTxDelay->setValue (txDelay_); ui_->sbTxDelay->setValue (txDelay_);
@ -1301,6 +1276,9 @@ void Configuration::impl::initialize_models ()
next_frequencies_.frequency_list (frequencies_.frequency_list ()); next_frequencies_.frequency_list (frequencies_.frequency_list ());
next_stations_.station_list (stations_.station_list ()); next_stations_.station_list (stations_.station_list ());
next_decode_highlighing_model_.items (decode_highlighing_model_.items ());
ui_->LotW_days_since_upload_spin_box->setValue (LotW_days_since_upload_);
set_rig_invariants (); set_rig_invariants ();
} }
@ -1324,16 +1302,6 @@ void Configuration::impl::read_settings ()
RTTY_exchange_ = settings_->value ("RTTYExchange",QString {}).toString (); RTTY_exchange_ = settings_->value ("RTTYExchange",QString {}).toString ();
ui_->FieldDay_Exchange->setText(FD_exchange_); ui_->FieldDay_Exchange->setText(FD_exchange_);
ui_->RTTY_Exchange->setText(RTTY_exchange_); ui_->RTTY_Exchange->setText(RTTY_exchange_);
next_color_CQ_ = color_CQ_ = settings_->value("colorCQ","#66ff66").toString();
next_color_MyCall_ = color_MyCall_ = settings_->value("colorMyCall","#ff6666").toString();
next_color_TxMsg_ = color_TxMsg_ = settings_->value("colorTxMsg","#ffff00").toString();
next_color_DXCC_ = color_DXCC_ = settings_->value("colorDXCC","#ff00ff").toString();
next_color_DXCCband_ = color_DXCCband_ = settings_->value("colorDXCCband","#ffaaff").toString();
next_color_NewCall_ = color_NewCall_ = settings_->value("colorNewCall","#66b2ff").toString();
next_color_NewCallBand_ = color_NewCallBand_ = settings_->value("colorNewCallBand","#99ffff").toString();
next_color_NewGrid_ = color_NewGrid_ = settings_->value("colorNewGrid","#ffaa00").toString();
next_color_NewGridBand_ = color_NewGridBand_ = settings_->value("colorNewGridBand","#ffcc99").toString();
next_color_LoTW_ = color_LoTW_ = settings_->value("colorLoTW","#990000").toString();
if (next_font_.fromString (settings_->value ("Font", QGuiApplication::font ().toString ()).toString ()) if (next_font_.fromString (settings_->value ("Font", QGuiApplication::font ().toString ()).toString ())
&& next_font_ != font_) && next_font_ != font_)
{ {
@ -1348,6 +1316,8 @@ void Configuration::impl::read_settings ()
&& next_decoded_text_font_ != decoded_text_font_) && next_decoded_text_font_ != decoded_text_font_)
{ {
decoded_text_font_ = next_decoded_text_font_; decoded_text_font_ = next_decoded_text_font_;
next_decode_highlighing_model_.set_font (decoded_text_font_);
ui_->highlighting_list_view->reset ();
Q_EMIT self_->decoded_text_font_changed (decoded_text_font_); Q_EMIT self_->decoded_text_font_changed (decoded_text_font_);
} }
else else
@ -1451,6 +1421,10 @@ void Configuration::impl::read_settings ()
stations_.station_list (settings_->value ("stations").value<StationList::Stations> ()); stations_.station_list (settings_->value ("stations").value<StationList::Stations> ());
decode_highlighing_model_.items (settings_->value ("DecodeHighlighting", QVariant::fromValue (DecodeHighlightingModel::default_items ())).value<DecodeHighlightingModel::HighlightItems> ());
LotW_days_since_upload_ = settings_->value ("LotWDaysSinceLastUpload", 365).toInt ();
lotw_users_.set_age_constraint (LotW_days_since_upload_);
log_as_RTTY_ = settings_->value ("toRTTY", false).toBool (); log_as_RTTY_ = settings_->value ("toRTTY", false).toBool ();
report_in_comments_ = settings_->value("dBtoComments", false).toBool (); report_in_comments_ = settings_->value("dBtoComments", false).toBool ();
rig_params_.rig_name = settings_->value ("Rig", TransceiverFactory::basic_transceiver_name_).toString (); rig_params_.rig_name = settings_->value ("Rig", TransceiverFactory::basic_transceiver_name_).toString ();
@ -1521,16 +1495,6 @@ void Configuration::impl::write_settings ()
settings_->setValue ("MyGrid", my_grid_); settings_->setValue ("MyGrid", my_grid_);
settings_->setValue ("FieldDayExchange", FD_exchange_); settings_->setValue ("FieldDayExchange", FD_exchange_);
settings_->setValue ("RTTYExchange", RTTY_exchange_); settings_->setValue ("RTTYExchange", RTTY_exchange_);
settings_->setValue("colorCQ",color_CQ_);
settings_->setValue("colorMyCall",color_MyCall_);
settings_->setValue("colorTxMsg",color_TxMsg_);
settings_->setValue("colorDXCC",color_DXCC_);
settings_->setValue("colorDXCCband",color_DXCCband_);
settings_->setValue("colorNewCall",color_NewCall_);
settings_->setValue("colorNewCallBand",color_NewCallBand_);
settings_->setValue("colorNewGrid",color_NewGrid_);
settings_->setValue("colorNewGridBand",color_NewGridBand_);
settings_->setValue("colorLoTW",color_LoTW_);
settings_->setValue ("Font", font_.toString ()); settings_->setValue ("Font", font_.toString ());
settings_->setValue ("DecodedTextFont", decoded_text_font_.toString ()); settings_->setValue ("DecodedTextFont", decoded_text_font_.toString ());
settings_->setValue ("IDint", id_interval_); settings_->setValue ("IDint", id_interval_);
@ -1572,6 +1536,8 @@ void Configuration::impl::write_settings ()
settings_->setValue ("Macros", macros_.stringList ()); settings_->setValue ("Macros", macros_.stringList ());
settings_->setValue ("FrequenciesForRegionModes", QVariant::fromValue (frequencies_.frequency_list ())); settings_->setValue ("FrequenciesForRegionModes", QVariant::fromValue (frequencies_.frequency_list ()));
settings_->setValue ("stations", QVariant::fromValue (stations_.station_list ())); settings_->setValue ("stations", QVariant::fromValue (stations_.station_list ()));
settings_->setValue ("DecodeHighlighting", QVariant::fromValue (decode_highlighing_model_.items ()));
settings_->setValue ("LotWDaysSinceLastUpload", LotW_days_since_upload_);
settings_->setValue ("toRTTY", log_as_RTTY_); settings_->setValue ("toRTTY", log_as_RTTY_);
settings_->setValue ("dBtoComments", report_in_comments_); settings_->setValue ("dBtoComments", report_in_comments_);
settings_->setValue ("Rig", rig_params_.rig_name); settings_->setValue ("Rig", rig_params_.rig_name);
@ -1895,20 +1861,11 @@ void Configuration::impl::accept ()
if (next_decoded_text_font_ != decoded_text_font_) if (next_decoded_text_font_ != decoded_text_font_)
{ {
decoded_text_font_ = next_decoded_text_font_; decoded_text_font_ = next_decoded_text_font_;
next_decode_highlighing_model_.set_font (decoded_text_font_);
ui_->highlighting_list_view->reset ();
Q_EMIT self_->decoded_text_font_changed (decoded_text_font_); Q_EMIT self_->decoded_text_font_changed (decoded_text_font_);
} }
color_CQ_ = next_color_CQ_;
color_MyCall_ = next_color_MyCall_;
color_TxMsg_ = next_color_TxMsg_;
color_DXCC_ = next_color_DXCC_;
color_DXCCband_ = next_color_DXCCband_;
color_NewCall_ = next_color_NewCall_;
color_NewCallBand_ = next_color_NewCallBand_;
color_NewGrid_ = next_color_NewGrid_;
color_NewGridBand_ = next_color_NewGridBand_;
color_LoTW_ = next_color_LoTW_;
rig_params_ = temp_rig_params; // now we can go live with the rig rig_params_ = temp_rig_params; // now we can go live with the rig
// related configuration parameters // related configuration parameters
rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name; rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name;
@ -2055,10 +2012,8 @@ void Configuration::impl::accept ()
} }
accept_udp_requests_ = ui_->accept_udp_requests_check_box->isChecked (); accept_udp_requests_ = ui_->accept_udp_requests_check_box->isChecked ();
auto new_n1mm_server = ui_->n1mm_server_name_line_edit->text (); n1mm_server_name_ = ui_->n1mm_server_name_line_edit->text ();
n1mm_server_name_ = new_n1mm_server; n1mm_server_port_ = ui_->n1mm_server_port_spin_box->value ();
auto new_n1mm_port = ui_->n1mm_server_port_spin_box->value ();
n1mm_server_port_ = new_n1mm_port;
broadcast_to_n1mm_ = ui_->enable_n1mm_broadcast_check_box->isChecked (); broadcast_to_n1mm_ = ui_->enable_n1mm_broadcast_check_box->isChecked ();
udpWindowToFront_ = ui_->udpWindowToFront->isChecked (); udpWindowToFront_ = ui_->udpWindowToFront->isChecked ();
@ -2079,10 +2034,18 @@ void Configuration::impl::accept ()
if (stations_.station_list () != next_stations_.station_list ()) if (stations_.station_list () != next_stations_.station_list ())
{ {
stations_.station_list(next_stations_.station_list ()); stations_.station_list (next_stations_.station_list ());
stations_.sort (StationList::band_column); stations_.sort (StationList::band_column);
} }
if (decode_highlighing_model_.items () != next_decode_highlighing_model_.items ())
{
decode_highlighing_model_.items (next_decode_highlighing_model_.items ());
Q_EMIT self_->decode_highlighting_changed (decode_highlighing_model_);
}
LotW_days_since_upload_ = ui_->LotW_days_since_upload_spin_box->value ();
lotw_users_.set_age_constraint (LotW_days_since_upload_);
if (ui_->use_dynamic_grid->isChecked() && !use_dynamic_grid_ ) if (ui_->use_dynamic_grid->isChecked() && !use_dynamic_grid_ )
{ {
// turning on so clear it so only the next location update gets used // turning on so clear it so only the next location update gets used
@ -2121,136 +2084,27 @@ void Configuration::impl::on_font_push_button_clicked ()
next_font_ = QFontDialog::getFont (0, next_font_, this); next_font_ = QFontDialog::getFont (0, next_font_, this);
} }
void Configuration::impl::on_pbCQmsg_clicked() void Configuration::impl::on_reset_highlighting_to_defaults_push_button_clicked (bool /*checked*/)
{ {
auto new_color = QColorDialog::getColor(next_color_CQ_, this, "CQ Messages Color"); if (MessageBox::Yes == MessageBox::query_message (this
if (new_color.isValid ()) , tr ("Reset Decode Highlighting")
, tr ("Reset all decode highlighting and priorities to default values")))
{ {
next_color_CQ_ = new_color; next_decode_highlighing_model_.items (DecodeHighlightingModel::default_items ());
ui_->labCQ->setStyleSheet(QString("background: %1").arg(next_color_CQ_.name()));
} }
} }
void Configuration::impl::on_pbMyCall_clicked() void Configuration::impl::on_LotW_CSV_fetch_push_button_clicked (bool /*checked*/)
{ {
auto new_color = QColorDialog::getColor(next_color_MyCall_, this, "My Call Messages Color"); lotw_users_.load (ui_->LotW_CSV_URL_line_edit->text (), true);
if (new_color.isValid ()) ui_->LotW_CSV_fetch_push_button->setEnabled (false);
{
next_color_MyCall_ = new_color;
ui_->labMyCall->setStyleSheet(QString("background: %1").arg(next_color_MyCall_.name()));
}
}
void Configuration::impl::on_pbTxMsg_clicked()
{
auto new_color = QColorDialog::getColor(next_color_TxMsg_, this, "Tx Messages Color");
if (new_color.isValid ())
{
next_color_TxMsg_ = new_color;
ui_->labTx->setStyleSheet(QString("background: %1").arg(next_color_TxMsg_.name()));
}
}
void Configuration::impl::on_pbNewDXCC_clicked()
{
auto new_color = QColorDialog::getColor(next_color_DXCC_, this, "New DXCC Messages Color");
if (new_color.isValid ())
{
next_color_DXCC_ = new_color;
ui_->labDXCC->setStyleSheet(QString("background: %1").arg(next_color_DXCC_.name()));
}
}
void Configuration::impl::on_pbNewDXCCband_clicked()
{
auto new_color = QColorDialog::getColor(next_color_DXCCband_, this, "New DXCCband Color");
if (new_color.isValid ())
{
next_color_DXCCband_ = new_color;
ui_->labDXCCband->setStyleSheet(QString("background: %1").arg(next_color_DXCCband_.name()));
}
}
void Configuration::impl::on_pbNewCall_clicked()
{
auto new_color = QColorDialog::getColor(next_color_NewCall_, this, "New Call Messages Color");
if (new_color.isValid ())
{
next_color_NewCall_ = new_color;
ui_->labNewCall->setStyleSheet(QString("background: %1").arg(next_color_NewCall_.name()));
}
}
void Configuration::impl::on_pbNewCallBand_clicked()
{
auto new_color = QColorDialog::getColor(next_color_NewCallBand_, this, "New CallBand Color");
if (new_color.isValid ())
{
next_color_NewCallBand_ = new_color;
ui_->labNewCallBand->setStyleSheet(QString("background: %1").arg(next_color_NewCallBand_.name()));
}
}
void Configuration::impl::on_pbNewGrid_clicked()
{
auto new_color = QColorDialog::getColor(next_color_NewGrid_, this, "New Grid Messages Color");
if (new_color.isValid ())
{
next_color_NewGrid_ = new_color;
ui_->labNewGrid->setStyleSheet(QString("background: %1").arg(next_color_NewGrid_.name()));
}
}
void Configuration::impl::on_pbNewGridBand_clicked()
{
auto new_color = QColorDialog::getColor(next_color_NewGridBand_, this, "New GridBand Messages Color");
if (new_color.isValid ())
{
next_color_NewGridBand_ = new_color;
ui_->labNewGridBand->setStyleSheet(QString("background: %1").arg(next_color_NewGridBand_.name()));
}
}
void Configuration::impl::on_pbLoTW_clicked()
{
auto new_color = QColorDialog::getColor(next_color_LoTW_, this, "Not in LoTW Color");
if (new_color.isValid ()) {
next_color_LoTW_ = new_color;
ui_->labLoTW->setStyleSheet(QString("color: %1").arg(next_color_LoTW_.name()));
}
}
void Configuration::impl::on_pbResetDefaults_clicked()
{
next_color_CQ_ = color_CQ_ = "#66ff66";
next_color_MyCall_ = color_MyCall_ = "#ff6666";
next_color_TxMsg_ = color_TxMsg_ = "#ffff00";
next_color_DXCC_ = color_DXCC_ = "#ff00ff";
next_color_DXCCband_ = color_DXCCband_ = "#ffaaff";
next_color_NewCall_ = color_NewCall_ = "#66b2ff";
next_color_NewCallBand_ = color_NewCallBand_ = "#99ffff";
next_color_NewGrid_ = color_NewGrid_ = "#ffaa00";
next_color_NewGridBand_ = color_NewGridBand_ = "#ffcc99";
next_color_LoTW_ = color_LoTW_ = "#5500ff";
ui_->labCQ->setStyleSheet(QString("background: %1").arg(next_color_CQ_.name()));
ui_->labMyCall->setStyleSheet(QString("background: %1").arg(next_color_MyCall_.name()));
ui_->labTx->setStyleSheet(QString("background: %1").arg(next_color_TxMsg_.name()));
ui_->labDXCC->setStyleSheet(QString("background: %1").arg(next_color_DXCC_.name()));
ui_->labDXCCband->setStyleSheet(QString("background: %1").arg(next_color_DXCCband_.name()));
ui_->labNewCall->setStyleSheet(QString("background: %1").arg(next_color_NewCall_.name()));
ui_->labNewCallBand->setStyleSheet(QString("background: %1").arg(next_color_NewCallBand_.name()));
ui_->labNewGrid->setStyleSheet(QString("background: %1").arg(next_color_NewGrid_.name()));
ui_->labNewGridBand->setStyleSheet(QString("background: %1").arg(next_color_NewGridBand_.name()));
ui_->labLoTW->setStyleSheet(QString("color: %1").arg(next_color_LoTW_.name()));
} }
void Configuration::impl::on_decoded_text_font_push_button_clicked () void Configuration::impl::on_decoded_text_font_push_button_clicked ()
{ {
next_decoded_text_font_ = QFontDialog::getFont (0, decoded_text_font_ , this next_decoded_text_font_ = QFontDialog::getFont (0, decoded_text_font_ , this
, tr ("WSJT-X Decoded Text Font Chooser") , tr ("WSJT-X Decoded Text Font Chooser")
#if QT_VERSION >= 0x050201
, QFontDialog::MonospacedFonts , QFontDialog::MonospacedFonts
#endif
); );
} }
@ -2635,11 +2489,10 @@ void Configuration::impl::on_cbHound_clicked (bool checked)
void Configuration::impl::chk77() void Configuration::impl::chk77()
{ {
bool b77OK = !ui_->cbFox->isChecked() and !ui_->cbHound->isChecked(); bool b77OK = !ui_->cbFox->isChecked() and !ui_->cbHound->isChecked();
ui_->groupBox_8->setEnabled(b77OK);
ui_->groupBox_9->setEnabled(b77OK); ui_->groupBox_9->setEnabled(b77OK);
if(!b77OK) { if(!b77OK) {
ui_->cbGenerate77->setChecked(false); ui_->cbGenerate77->setChecked(true);
ui_->cbDecode77->setChecked(false); ui_->cbDecode77->setChecked(true);
} }
} }
@ -3068,11 +2921,6 @@ auto Configuration::impl::remove_calibration (Frequency f) const -> Frequency
/ (1. + calibration_.slope_ppm / 1.e6)); / (1. + calibration_.slope_ppm / 1.e6));
} }
#if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_IMPL (Configuration, DataMode);
ENUM_QDEBUG_OPS_IMPL (Configuration, Type2MsgGen);
#endif
ENUM_QDATASTREAM_OPS_IMPL (Configuration, DataMode); ENUM_QDATASTREAM_OPS_IMPL (Configuration, DataMode);
ENUM_QDATASTREAM_OPS_IMPL (Configuration, Type2MsgGen); ENUM_QDATASTREAM_OPS_IMPL (Configuration, Type2MsgGen);

View File

@ -16,11 +16,14 @@ class QWidget;
class QAudioDeviceInfo; class QAudioDeviceInfo;
class QString; class QString;
class QDir; class QDir;
class QNetworkAccessManager;
class Bands; class Bands;
class FrequencyList_v2; class FrequencyList_v2;
class StationList; class StationList;
class QStringListModel; class QStringListModel;
class QHostAddress; class QHostAddress;
class LotWUsers;
class DecodeHighlightingModel;
// //
// Class Configuration // Class Configuration
@ -56,7 +59,6 @@ class Configuration final
: public QObject : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_ENUMS (DataMode Type2MsgGen)
public: public:
using MODE = Transceiver::MODE; using MODE = Transceiver::MODE;
@ -69,7 +71,7 @@ public:
enum Type2MsgGen {type_2_msg_1_full, type_2_msg_3_full, type_2_msg_5_only}; enum Type2MsgGen {type_2_msg_1_full, type_2_msg_3_full, type_2_msg_5_only};
Q_ENUM (Type2MsgGen) Q_ENUM (Type2MsgGen)
explicit Configuration (QDir const& temp_directory, QSettings * settings, explicit Configuration (QNetworkAccessManager *, QDir const& temp_directory, QSettings * settings,
QWidget * parent = nullptr); QWidget * parent = nullptr);
~Configuration (); ~Configuration ();
@ -170,18 +172,10 @@ public:
QDir azel_directory () const; QDir azel_directory () const;
QString rig_name () const; QString rig_name () const;
Type2MsgGen type_2_msg_gen () const; Type2MsgGen type_2_msg_gen () const;
QColor color_CQ () const;
QColor color_MyCall () const;
QColor color_TxMsg () const;
QColor color_DXCC () const;
QColor color_DXCCband () const;
QColor color_NewCall () const;
QColor color_NewCallBand () const;
QColor color_NewGrid () const;
QColor color_NewGridBand () const;
QColor color_LoTW() const;
bool pwrBandTxMemory () const; bool pwrBandTxMemory () const;
bool pwrBandTuneMemory () const; bool pwrBandTuneMemory () const;
LotWUsers const& lotw_users () const;
DecodeHighlightingModel const& decode_highlighting () const;
struct CalibrationParams struct CalibrationParams
{ {
@ -240,8 +234,6 @@ public:
Q_SLOT void transceiver_tx_frequency (Frequency = 0u); Q_SLOT void transceiver_tx_frequency (Frequency = 0u);
// Set transceiver mode. // Set transceiver mode.
//
// Rationalise means ensure TX uses same mode as RX.
Q_SLOT void transceiver_mode (MODE); Q_SLOT void transceiver_mode (MODE);
// Set/unset PTT. // Set/unset PTT.
@ -266,15 +258,17 @@ public:
// These signals indicate a font has been selected and accepted for // These signals indicate a font has been selected and accepted for
// the application text and decoded text respectively. // the application text and decoded text respectively.
// //
Q_SIGNAL void text_font_changed (QFont); Q_SIGNAL void text_font_changed (QFont) const;
Q_SIGNAL void decoded_text_font_changed (QFont); Q_SIGNAL void decoded_text_font_changed (QFont) const;
// //
// This signal is emitted when the UDP server changes // This signal is emitted when the UDP server changes
// //
Q_SIGNAL void udp_server_changed (QString const& udp_server); Q_SIGNAL void udp_server_changed (QString const& udp_server) const;
Q_SIGNAL void udp_server_port_changed (port_type server_port); Q_SIGNAL void udp_server_port_changed (port_type server_port) const;
// signal updates to decode highlighting
Q_SIGNAL void decode_highlighting_changed (DecodeHighlightingModel const&) const;
// //
// These signals are emitted and reflect transceiver state changes // These signals are emitted and reflect transceiver state changes
@ -296,16 +290,6 @@ private:
pimpl<impl> m_; pimpl<impl> m_;
}; };
#if QT_VERSION < 0x050500
Q_DECLARE_METATYPE (Configuration::DataMode);
Q_DECLARE_METATYPE (Configuration::Type2MsgGen);
#endif
#if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_DECL (Configuration, DataMode);
ENUM_QDEBUG_OPS_DECL (Configuration, Type2MsgGen);
#endif
ENUM_QDATASTREAM_OPS_DECL (Configuration, DataMode); ENUM_QDATASTREAM_OPS_DECL (Configuration, DataMode);
ENUM_QDATASTREAM_OPS_DECL (Configuration, Type2MsgGen); ENUM_QDATASTREAM_OPS_DECL (Configuration, Type2MsgGen);

View File

@ -74,7 +74,7 @@
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLineEdit" name="grid_line_edit"> <widget class="QLineEdit" name="grid_line_edit">
<property name="toolTip"> <property name="toolTip">
<string>Maidenhead locator (only the first four characters are required).</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Maidenhead locator, preferably 6 characters.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -103,7 +103,11 @@
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QComboBox" name="region_combo_box"/> <widget class="QComboBox" name="region_combo_box">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select your IARU region.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item> </item>
</layout> </layout>
</item> </item>
@ -1700,36 +1704,39 @@ QListView::item:hover {
<property name="text"> <property name="text">
<string>Op Call:</string> <string>Op Call:</string>
</property> </property>
<property name="buddy">
<cstring>opCallEntry</cstring>
</property>
</widget> </widget>
</item> </item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QCheckBox" name="report_in_comments_check_box"> <widget class="QCheckBox" name="report_in_comments_check_box">
<property name="toolTip"> <property name="toolTip">
<string>Some logging programs will not accept the type of reports <string>Some logging programs will not accept JT-65 or JT9 as a recognized mode.</string>
saved by this program.
Check this option to save the sent and received reports in the
comments field.</string>
</property> </property>
<property name="text"> <property name="text">
<string>d&amp;B reports to comments</string> <string>Con&amp;vert mode to RTTY</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0" colspan="2"> <item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="clear_DX_check_box"> <widget class="QCheckBox" name="clear_DX_check_box">
<property name="toolTip"> <property name="toolTip">
<string>Check this option to force the clearing of the DX Call <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The callsign of the operator, if different from the station callsign.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
and DX Grid fields when a 73 or free text message is sent.</string>
</property> </property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="cbAutoLog">
<property name="text"> <property name="text">
<string>Clear &amp;DX call and grid after logging</string> <string>Log automatically</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QCheckBox" name="log_as_RTTY_check_box"> <widget class="QCheckBox" name="log_as_RTTY_check_box">
<property name="toolTip"> <property name="toolTip">
<string>Some logging programs will not accept JT-65 or JT9 as a recognized mode.</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Some logging programs will not accept WSJT-X mode names.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Con&amp;vert mode to RTTY</string> <string>Con&amp;vert mode to RTTY</string>
@ -1745,6 +1752,9 @@ and DX Grid fields when a 73 or free text message is sent.</string>
</item> </item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QCheckBox" name="cbAutoLog"> <widget class="QCheckBox" name="cbAutoLog">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Check to have QSOs logged automatically, when complete.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Log automatically</string> <string>Log automatically</string>
</property> </property>
@ -1902,6 +1912,9 @@ for assessing propagation and system performance.</string>
<property name="text"> <property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;N1MM Server name or IP address:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;N1MM Server name or IP address:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="buddy">
<cstring>n1mm_server_name_line_edit</cstring>
</property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
@ -1916,6 +1929,9 @@ for assessing propagation and system performance.</string>
<property name="text"> <property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;N1MM Server port number:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;N1MM Server port number:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="buddy">
<cstring>n1mm_server_port_spin_box</cstring>
</property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="2" column="1">
@ -2159,8 +2175,158 @@ Right click for insert and delete options.</string>
<attribute name="title"> <attribute name="title">
<string>Colors</string> <string>Colors</string>
</attribute> </attribute>
<layout class="QGridLayout" name="gridLayout_5" rowstretch="1,0,0" columnstretch="1,0,0"> <layout class="QVBoxLayout" name="verticalLayout_7">
<item row="0" column="1"> <item>
<widget class="QGroupBox" name="groupBox_12">
<property name="title">
<string>Decode Highlightling</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<item>
<widget class="DecodeHighlightingListView" name="highlighting_list_view">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable or disable using the check boxes and right-click an item to change the foreground color, background color, or reset the item to default values.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="dragEnabled">
<bool>true</bool>
</property>
<property name="dragDropMode">
<enum>QAbstractItemView::InternalMove</enum>
</property>
<property name="defaultDropAction">
<enum>Qt::MoveAction</enum>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="resizeMode">
<enum>QListView::Adjust</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="reset_highlighting_to_defaults_push_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Push to reset all highlight items above to default values and priorities.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Reset Highlighting</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_11">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Controls for Logbook of the World user lookup.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="title">
<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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Adjust this spin box to set the age threshold of LotW user's last upload date that is accepted as a current LotW user.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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">
<string>Users CSV file URL:</string>
</property>
<property name="buddy">
<cstring>LotW_CSV_URL_line_edit</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_20">
<item>
<widget class="QLineEdit" name="LotW_CSV_URL_line_edit">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;URL of the ARRL LotW user's last upload dates and times data file which is used to highlight decodes from stations that are known to upload their log file to LotW.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>https://lotw.arrl.org/lotw-user-activity.csv</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="LotW_CSV_fetch_push_button">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Push this button to fetch the latest LotW user's upload date and time data file.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Fetch Now</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<spacer name="horizontalSpacer_8"> <spacer name="horizontalSpacer_8">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -2173,317 +2339,6 @@ Right click for insert and delete options.</string>
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_13">
<item row="9" column="1">
<widget class="QLabel" name="labLoTW">
<property name="styleSheet">
<string notr="true">QLabel{color: #990000}</string>
</property>
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pbMyCall">
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>My Call in message</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QPushButton" name="pbNewDXCCband">
<property name="text">
<string>New DXCC on Band</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="labDXCCband">
<property name="styleSheet">
<string notr="true">QLabel{background-color: #ffaaff}
</string>
</property>
<property name="text">
<string notr="true">K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="pbCQmsg">
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>CQ in message</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="labTx">
<property name="minimumSize">
<size>
<width>80</width>
<height>20</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QLabel{background-color: yellow}</string>
</property>
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="pbTxMsg">
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Transmitted message</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="labMyCall">
<property name="minimumSize">
<size>
<width>80</width>
<height>20</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QLabel{background-color: #ff6666}</string>
</property>
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="labCQ">
<property name="minimumSize">
<size>
<width>80</width>
<height>20</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QLabel{background-color: #66ff66}</string>
</property>
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="labDXCC">
<property name="minimumSize">
<size>
<width>80</width>
<height>20</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QLabel{background-color: #ff00ff}</string>
</property>
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QPushButton" name="pbResetDefaults">
<property name="text">
<string>Reset Defaults</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="pbNewDXCC">
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>New DXCC</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="labNewGrid">
<property name="styleSheet">
<string notr="true">QLabel{background-color: #ff8000}</string>
</property>
<property name="text">
<string notr="true">K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="labNewGridBand">
<property name="styleSheet">
<string notr="true">QLabel{background-color: #ffcc99}</string>
</property>
<property name="text">
<string notr="true">K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="labNewCall">
<property name="minimumSize">
<size>
<width>80</width>
<height>20</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">QLabel{background-color: #00ffff}</string>
</property>
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QPushButton" name="pbNewGrid">
<property name="text">
<string>New grid</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QPushButton" name="pbNewGridBand">
<property name="text">
<string>New Grid on Band</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="labNewCallBand">
<property name="styleSheet">
<string notr="true">QLabel{background-color: #99ffff}</string>
</property>
<property name="text">
<string notr="true">K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QPushButton" name="pbNewCall">
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>New Call</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QPushButton" name="pbNewCallBand">
<property name="text">
<string>New Call on Band</string>
</property>
</widget>
</item>
<item row="9" column="0">
<widget class="QPushButton" name="pbLoTW">
<property name="text">
<string>No LoTW</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer_10">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<spacer name="verticalSpacer_6">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>120</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>150</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="advanced_tab"> <widget class="QWidget" name="advanced_tab">
@ -2567,6 +2422,9 @@ Right click for insert and delete options.</string>
<layout class="QHBoxLayout" name="horizontalLayout_15"> <layout class="QHBoxLayout" name="horizontalLayout_15">
<item> <item>
<widget class="QCheckBox" name="cbGenerate77"> <widget class="QCheckBox" name="cbGenerate77">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;By default, early candidate releases of WSJT-X 2.0 generate 75-bit messages if the message content allows it.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Always generate 77-bit messages</string> <string>Always generate 77-bit messages</string>
</property> </property>
@ -2574,6 +2432,9 @@ Right click for insert and delete options.</string>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="cbDecode77"> <widget class="QCheckBox" name="cbDecode77">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Check this box to ignore FT8 transmissions using the older 75-bit protocol.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Decode only 77-bit messages</string> <string>Decode only 77-bit messages</string>
</property> </property>
@ -2766,6 +2627,9 @@ Right click for insert and delete options.</string>
<layout class="QGridLayout" name="gridLayout_15" columnstretch="1,2,1,0"> <layout class="QGridLayout" name="gridLayout_15" columnstretch="1,2,1,0">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QRadioButton" name="rbNone"> <widget class="QRadioButton" name="rbNone">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;For normal operating&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>None</string> <string>None</string>
</property> </property>
@ -2782,6 +2646,9 @@ Right click for insert and delete options.</string>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;European VHF+ contests requiring a signal report, serial number, and 6-character locator.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>EU VHF Contest</string> <string>EU VHF Contest</string>
</property> </property>
@ -2791,6 +2658,9 @@ Right click for insert and delete options.</string>
<layout class="QHBoxLayout" name="horizontalLayout_18" stretch="2,1,1"> <layout class="QHBoxLayout" name="horizontalLayout_18" stretch="2,1,1">
<item> <item>
<widget class="QRadioButton" name="rbRTTYroundup"> <widget class="QRadioButton" name="rbRTTYroundup">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ARRL RTTY Roundup and similar contests. Exchange is US state, Canadian province, or &amp;quot;DX&amp;quot;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>ARRL RTTY Roundup</string> <string>ARRL RTTY Roundup</string>
</property> </property>
@ -2829,6 +2699,9 @@ Right click for insert and delete options.</string>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ARRL RTTY Roundup and similar contests. Exchange is US state, Canadian province, or &amp;quot;DX&amp;quot;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>NJ</string> <string>NJ</string>
</property> </property>
@ -2845,6 +2718,9 @@ Right click for insert and delete options.</string>
<layout class="QHBoxLayout" name="horizontalLayout_17" stretch="2,1,1"> <layout class="QHBoxLayout" name="horizontalLayout_17" stretch="2,1,1">
<item> <item>
<widget class="QRadioButton" name="rbFieldDay"> <widget class="QRadioButton" name="rbFieldDay">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ARRL Field Day exchange: number of transmitters, Class, and ARRL/RAC section or &amp;quot;DX&amp;quot;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>ARRL Field Day</string> <string>ARRL Field Day</string>
</property> </property>
@ -2883,6 +2759,9 @@ Right click for insert and delete options.</string>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;ARRL Field Day exchange: number of transmitters, Class, and ARRL/RAC section or &amp;quot;DX&amp;quot;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>6A SNJ</string> <string>6A SNJ</string>
</property> </property>
@ -2903,6 +2782,9 @@ Right click for insert and delete options.</string>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;North American VHF/UHF/Microwave contests and others in which a 4-character grid locator is the required exchange.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>NA VHF Contest</string> <string>NA VHF Contest</string>
</property> </property>
@ -2944,9 +2826,7 @@ Right click for insert and delete options.</string>
<item> <item>
<widget class="QDialogButtonBox" name="configuration_dialog_button_box"> <widget class="QDialogButtonBox" name="configuration_dialog_button_box">
<property name="toolTip"> <property name="toolTip">
<string>Discard or apply configuration changes including <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Discard (Cancel) or apply (OK) configuration changes including&lt;/p&gt;&lt;p&gt;resetting the radio interface and applying any soundcard changes&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
resetting the radio interface and applying any
soundcard changes</string>
</property> </property>
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
@ -2958,36 +2838,49 @@ soundcard changes</string>
</item> </item>
</layout> </layout>
</widget> </widget>
<customwidgets>
<customwidget>
<class>DecodeHighlightingListView</class>
<extends>QListView</extends>
<header>DecodehigHlightingListView.hpp</header>
</customwidget>
</customwidgets>
<tabstops> <tabstops>
<tabstop>configuration_tabs</tabstop> <tabstop>configuration_tabs</tabstop>
<tabstop>callsign_line_edit</tabstop> <tabstop>callsign_line_edit</tabstop>
<tabstop>grid_line_edit</tabstop> <tabstop>grid_line_edit</tabstop>
<tabstop>use_dynamic_grid</tabstop>
<tabstop>region_combo_box</tabstop> <tabstop>region_combo_box</tabstop>
<tabstop>type_2_msg_gen_combo_box</tabstop> <tabstop>type_2_msg_gen_combo_box</tabstop>
<tabstop>insert_blank_check_box</tabstop> <tabstop>insert_blank_check_box</tabstop>
<tabstop>miles_check_box</tabstop> <tabstop>miles_check_box</tabstop>
<tabstop>TX_messages_check_box</tabstop> <tabstop>TX_messages_check_box</tabstop>
<tabstop>DXCC_check_box</tabstop> <tabstop>DXCC_check_box</tabstop>
<tabstop>ppfx_check_box</tabstop>
<tabstop>font_push_button</tabstop> <tabstop>font_push_button</tabstop>
<tabstop>decoded_text_font_push_button</tabstop> <tabstop>decoded_text_font_push_button</tabstop>
<tabstop>monitor_off_check_box</tabstop> <tabstop>monitor_off_check_box</tabstop>
<tabstop>monitor_last_used_check_box</tabstop> <tabstop>monitor_last_used_check_box</tabstop>
<tabstop>quick_call_check_box</tabstop> <tabstop>quick_call_check_box</tabstop>
<tabstop>tx_watchdog_spin_box</tabstop> <tabstop>disable_TX_on_73_check_box</tabstop>
<tabstop>CW_id_after_73_check_box</tabstop> <tabstop>CW_id_after_73_check_box</tabstop>
<tabstop>enable_VHF_features_check_box</tabstop> <tabstop>enable_VHF_features_check_box</tabstop>
<tabstop>tx_QSY_check_box</tabstop> <tabstop>tx_QSY_check_box</tabstop>
<tabstop>single_decode_check_box</tabstop> <tabstop>single_decode_check_box</tabstop>
<tabstop>decode_at_52s_check_box</tabstop> <tabstop>decode_at_52s_check_box</tabstop>
<tabstop>tx_watchdog_spin_box</tabstop>
<tabstop>CW_id_interval_spin_box</tabstop> <tabstop>CW_id_interval_spin_box</tabstop>
<tabstop>rig_combo_box</tabstop> <tabstop>rig_combo_box</tabstop>
<tabstop>CAT_poll_interval_spin_box</tabstop> <tabstop>CAT_poll_interval_spin_box</tabstop>
<tabstop>CAT_port_combo_box</tabstop> <tabstop>CAT_port_combo_box</tabstop>
<tabstop>CAT_serial_baud_combo_box</tabstop> <tabstop>CAT_serial_baud_combo_box</tabstop>
<tabstop>CAT_default_bit_radio_button</tabstop>
<tabstop>CAT_7_bit_radio_button</tabstop> <tabstop>CAT_7_bit_radio_button</tabstop>
<tabstop>CAT_8_bit_radio_button</tabstop> <tabstop>CAT_8_bit_radio_button</tabstop>
<tabstop>CAT_default_stop_bit_radio_button</tabstop>
<tabstop>CAT_one_stop_bit_radio_button</tabstop> <tabstop>CAT_one_stop_bit_radio_button</tabstop>
<tabstop>CAT_two_stop_bit_radio_button</tabstop> <tabstop>CAT_two_stop_bit_radio_button</tabstop>
<tabstop>CAT_handshake_default_radio_button</tabstop>
<tabstop>CAT_handshake_none_radio_button</tabstop> <tabstop>CAT_handshake_none_radio_button</tabstop>
<tabstop>CAT_handshake_xon_radio_button</tabstop> <tabstop>CAT_handshake_xon_radio_button</tabstop>
<tabstop>CAT_handshake_hardware_radio_button</tabstop> <tabstop>CAT_handshake_hardware_radio_button</tabstop>
@ -3021,29 +2914,48 @@ soundcard changes</string>
<tabstop>delete_macro_push_button</tabstop> <tabstop>delete_macro_push_button</tabstop>
<tabstop>macros_list_view</tabstop> <tabstop>macros_list_view</tabstop>
<tabstop>prompt_to_log_check_box</tabstop> <tabstop>prompt_to_log_check_box</tabstop>
<tabstop>cbAutoLog</tabstop>
<tabstop>log_as_RTTY_check_box</tabstop> <tabstop>log_as_RTTY_check_box</tabstop>
<tabstop>report_in_comments_check_box</tabstop> <tabstop>report_in_comments_check_box</tabstop>
<tabstop>clear_DX_check_box</tabstop> <tabstop>clear_DX_check_box</tabstop>
<tabstop>opCallEntry</tabstop>
<tabstop>psk_reporter_check_box</tabstop> <tabstop>psk_reporter_check_box</tabstop>
<tabstop>udp_server_line_edit</tabstop> <tabstop>udp_server_line_edit</tabstop>
<tabstop>udp_server_port_spin_box</tabstop> <tabstop>udp_server_port_spin_box</tabstop>
<tabstop>accept_udp_requests_check_box</tabstop> <tabstop>accept_udp_requests_check_box</tabstop>
<tabstop>udpWindowToFront</tabstop> <tabstop>udpWindowToFront</tabstop>
<tabstop>udpWindowRestore</tabstop> <tabstop>udpWindowRestore</tabstop>
<tabstop>enable_n1mm_broadcast_check_box</tabstop>
<tabstop>n1mm_server_name_line_edit</tabstop>
<tabstop>n1mm_server_port_spin_box</tabstop>
<tabstop>calibration_slope_ppm_spin_box</tabstop> <tabstop>calibration_slope_ppm_spin_box</tabstop>
<tabstop>calibration_intercept_spin_box</tabstop> <tabstop>calibration_intercept_spin_box</tabstop>
<tabstop>frequencies_table_view</tabstop> <tabstop>frequencies_table_view</tabstop>
<tabstop>stations_table_view</tabstop> <tabstop>stations_table_view</tabstop>
<tabstop>pbCQmsg</tabstop> <tabstop>highlighting_list_view</tabstop>
<tabstop>pbMyCall</tabstop> <tabstop>reset_highlighting_to_defaults_push_button</tabstop>
<tabstop>pbTxMsg</tabstop> <tabstop>LotW_CSV_URL_line_edit</tabstop>
<tabstop>pbNewDXCC</tabstop> <tabstop>LotW_CSV_fetch_push_button</tabstop>
<tabstop>LotW_days_since_upload_spin_box</tabstop>
<tabstop>sbNtrials</tabstop> <tabstop>sbNtrials</tabstop>
<tabstop>sbAggressive</tabstop> <tabstop>sbAggressive</tabstop>
<tabstop>cbTwoPass</tabstop> <tabstop>cbTwoPass</tabstop>
<tabstop>sbDegrade</tabstop> <tabstop>sbDegrade</tabstop>
<tabstop>sbBandwidth</tabstop> <tabstop>sbBandwidth</tabstop>
<tabstop>sbTxDelay</tabstop> <tabstop>sbTxDelay</tabstop>
<tabstop>cbx2ToneSpacing</tabstop>
<tabstop>cbx4ToneSpacing</tabstop>
<tabstop>cbFox</tabstop>
<tabstop>cbHound</tabstop>
<tabstop>cbGenerate77</tabstop>
<tabstop>cbDecode77</tabstop>
<tabstop>rbNone</tabstop>
<tabstop>rbNA_VHF_Contest</tabstop>
<tabstop>rbEU_VHF_Contest</tabstop>
<tabstop>rbFieldDay</tabstop>
<tabstop>FieldDay_Exchange</tabstop>
<tabstop>rbRTTYroundup</tabstop>
<tabstop>RTTY_Exchange</tabstop>
</tabstops> </tabstops>
<resources/> <resources/>
<connections> <connections>
@ -3113,12 +3025,12 @@ soundcard changes</string>
</connection> </connection>
</connections> </connections>
<buttongroups> <buttongroups>
<buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="CAT_handshake_button_group"/> <buttongroup name="CAT_handshake_button_group"/>
<buttongroup name="CAT_stop_bits_button_group"/> <buttongroup name="CAT_data_bits_button_group"/>
<buttongroup name="TX_mode_button_group"/> <buttongroup name="TX_mode_button_group"/>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="TX_audio_source_button_group"/> <buttongroup name="TX_audio_source_button_group"/>
<buttongroup name="split_mode_button_group"/>
<buttongroup name="CAT_stop_bits_button_group"/>
<buttongroup name="PTT_method_button_group"/> <buttongroup name="PTT_method_button_group"/>
</buttongroups> </buttongroups>
</ui> </ui>

View File

@ -0,0 +1,77 @@
#include "DecodeHighlightingListView.hpp"
#include <QAction>
#include <QColorDialog>
#include "DecodeHighlightingModel.hpp"
#include "MessageBox.hpp"
#include "pimpl_impl.hpp"
class DecodeHighlightingListView::impl final
{
public:
impl ()
: fg_colour_action_ {tr ("&Foreground color ..."), nullptr}
, bg_colour_action_ {tr ("&Background color ..."), nullptr}
, defaults_action_ {tr ("&Reset this item to defaults"), nullptr}
{
}
DecodeHighlightingListView * self_;
QAction fg_colour_action_;
QAction bg_colour_action_;
QAction defaults_action_;
};
DecodeHighlightingListView::DecodeHighlightingListView (QWidget * parent)
: QListView {parent}
{
addAction (&m_->fg_colour_action_);
addAction (&m_->bg_colour_action_);
addAction (&m_->defaults_action_);
connect (&m_->fg_colour_action_, &QAction::triggered, [this] (bool /*checked*/) {
auto const& index = currentIndex ();
auto colour = QColorDialog::getColor (model ()->data (index, Qt::ForegroundRole).value<QBrush> ().color ()
, this
, tr ("Choose %1 Foreground Color")
.arg (model ()->data (index).toString ()));
if (colour.isValid ())
{
model ()->setData (index, colour, Qt::ForegroundRole);
}
});
connect (&m_->bg_colour_action_, &QAction::triggered, [this] (bool /*checked*/) {
auto const& index = currentIndex ();
auto colour = QColorDialog::getColor (model ()->data (index, Qt::BackgroundRole).value<QBrush> ().color ()
, this
, tr ("Choose %1 Background Color")
.arg (model ()->data (index).toString ()));
if (colour.isValid ())
{
model ()->setData (index, colour, Qt::BackgroundRole);
}
});
connect (&m_->defaults_action_, &QAction::triggered, [this] (bool /*checked*/) {
auto const& index = currentIndex ();
model ()->setData (index, model ()->data (index, DecodeHighlightingModel::EnabledDefaultRole).toBool () ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
model ()->setData (index, model ()->data (index, DecodeHighlightingModel::ForegroundDefaultRole), Qt::ForegroundRole);
model ()->setData (index, model ()->data (index, DecodeHighlightingModel::BackgroundDefaultRole), Qt::BackgroundRole);
});
}
DecodeHighlightingListView::~DecodeHighlightingListView ()
{
}
QSize DecodeHighlightingListView::sizeHint () const
{
auto item_height = sizeHintForRow (0);
if (item_height >= 0)
{
// set the height hint to exactly the space required for all the
// items
return {width (), (model ()->rowCount () * (item_height + 2 * spacing ())) + 2 * frameWidth ()};
}
return QListView::sizeHint ();
}

View File

@ -0,0 +1,32 @@
#ifndef DECODE_HIGHLIGHTING_LIST_VIEW_HPP_
#define DECODE_HIGHLIGHTING_LIST_VIEW_HPP_
#include <QListView>
#include "pimpl_h.hpp"
class QWidget;
// Class Decode Highlighting List View
//
// Sub-class of a QListView that adds a context menu to adjust the
// foreground and background colour roles of the the underlying model
// item that lies at the context menu right-click position. It also
// constrains the vertical size hint to limit the height to exactly
// that of the sum of the items.
//
class DecodeHighlightingListView final
: public QListView
{
public:
explicit DecodeHighlightingListView (QWidget * parent = nullptr);
~DecodeHighlightingListView ();
private:
QSize sizeHint () const override;
class impl;
pimpl<impl> m_;
};
#endif

319
DecodeHighlightingModel.cpp Normal file
View File

@ -0,0 +1,319 @@
#include "DecodeHighlightingModel.hpp"
#include <QString>
#include <QVariant>
#include <QList>
#include <QBrush>
#include <QFont>
#include <QMap>
#include <QVector>
#include <QDataStream>
#include <QMetaType>
#include <QDebug>
#include "pimpl_impl.hpp"
#include "moc_DecodeHighlightingModel.cpp"
class DecodeHighlightingModel::impl final
{
public:
explicit impl ()
: data_ {defaults_}
{
}
HighlightItems static const defaults_;
HighlightItems data_;
QFont font_;
};
QList<DecodeHighlightingModel::HighlightInfo> const DecodeHighlightingModel::impl::defaults_ = {
{Highlight::CQ, true, {}, {{0x66, 0xff, 0x66}}}
, {Highlight::MyCall, true, {}, {{0xff, 0x66, 0x66}}}
, {Highlight::Tx, true, {}, {{Qt::yellow}}}
, {Highlight::DXCC, true, {}, {{0xff, 0x00, 0xff}}}
, {Highlight::DXCCBand, true, {}, {{0xff, 0xaa, 0xff}}}
, {Highlight::Grid, false, {}, {{0xff, 0x80, 0x00}}}
, {Highlight::GridBand, false, {}, {{0xff, 0xcc, 0x99}}}
, {Highlight::Call, false, {}, {{0x00, 0xff, 0xff}}}
, {Highlight::CallBand, false, {}, {{0x99, 0xff, 0xff}}}
, {Highlight::LotW, false, {{0x99, 0x00, 0x00}}, {}}
};
bool operator == (DecodeHighlightingModel::HighlightInfo const& lhs, DecodeHighlightingModel::HighlightInfo const& rhs)
{
return lhs.type_ == rhs.type_
&& lhs.enabled_ == rhs.enabled_
&& lhs.foreground_ == rhs.foreground_
&& lhs.background_ == rhs.background_;
}
QDataStream& operator << (QDataStream& os, DecodeHighlightingModel::HighlightInfo const& item)
{
return os << item.type_
<< item.enabled_
<< item.foreground_
<< item.background_;
}
QDataStream& operator >> (QDataStream& is, DecodeHighlightingModel::HighlightInfo& item)
{
return is >> item.type_
>> item.enabled_
>> item.foreground_
>> item.background_;
}
#if !defined (QT_NO_DEBUG_STREAM)
QDebug operator << (QDebug debug, DecodeHighlightingModel::HighlightInfo const& item)
{
QDebugStateSaver save {debug};
debug.nospace () << "HighlightInfo("
<< item.type_ << ", "
<< item.enabled_ << ", "
<< item.foreground_ << ", "
<< item.background_ << ')';
return debug;
}
#endif
ENUM_QDATASTREAM_OPS_IMPL (DecodeHighlightingModel, Highlight);
ENUM_CONVERSION_OPS_IMPL (DecodeHighlightingModel, Highlight);
DecodeHighlightingModel::DecodeHighlightingModel (QObject * parent)
: QAbstractListModel {parent}
{
}
DecodeHighlightingModel::~DecodeHighlightingModel ()
{
}
QString DecodeHighlightingModel::highlight_name (Highlight h)
{
switch (h)
{
case Highlight::CQ: return "CQ in message";
case Highlight::MyCall: return "My Call in message";
case Highlight::Tx: return "Transmitted message";
case Highlight::DXCC: return "New DXCC";
case Highlight::DXCCBand: return "New DXCC on Band";
case Highlight::Grid: return "New Grid";
case Highlight::GridBand: return "New Grid on Band";
case Highlight::Call: return "New Call";
case Highlight::CallBand: return "New Call on Band";
case Highlight::LotW: return "LotW User";
}
return "Unknown";
}
auto DecodeHighlightingModel::default_items () -> HighlightItems const&
{
return impl::defaults_;
}
auto DecodeHighlightingModel::items () const -> HighlightItems const&
{
return m_->data_;
}
void DecodeHighlightingModel::items (HighlightItems const& items)
{
m_->data_ = items;
QVector<int> roles;
roles << Qt::CheckStateRole << Qt::ForegroundRole << Qt::BackgroundRole;
Q_EMIT dataChanged (index (0, 0), index (rowCount () - 1, 0), roles);
}
void DecodeHighlightingModel::set_font (QFont const& font)
{
m_->font_ = font;
}
int DecodeHighlightingModel::rowCount (const QModelIndex& parent) const
{
return parent.isValid () ? 0 : m_->data_.size ();
}
QVariant DecodeHighlightingModel::data (const QModelIndex& index, int role) const
{
QVariant result;
if (index.isValid () && index.row () < rowCount ())
{
auto const& item = m_->data_[index.row ()];
switch (role)
{
case Qt::CheckStateRole:
result = item.enabled_ ? Qt::Checked : Qt::Unchecked;
break;
case Qt::DisplayRole:
result = highlight_name (item.type_);
break;
case Qt::ForegroundRole:
if (Qt::NoBrush != item.foreground_.style ())
{
result = item.foreground_;
}
break;
case Qt::BackgroundRole:
if (Qt::NoBrush != item.background_.style ())
{
result = item.background_;
}
break;
case Qt::FontRole:
result = m_->font_;
break;
case TypeRole:
result = static_cast<int> (item.type_);
break;
case EnabledDefaultRole:
for (auto const& default_item : impl::defaults_)
{
if (default_item.type_ == item.type_)
{
result = default_item.enabled_ ? Qt::Checked : Qt::Unchecked;
}
}
break;
case ForegroundDefaultRole:
for (auto const& default_item : impl::defaults_)
{
if (default_item.type_ == item.type_)
{
result = default_item.foreground_;
}
}
break;
case BackgroundDefaultRole:
for (auto const& default_item : impl::defaults_)
{
if (default_item.type_ == item.type_)
{
result = default_item.background_;
}
}
break;
}
}
return result;
}
// Override QAbstractItemModel::itemData() as it is used by the
// default mime encode routine used in drag'n'drop operations and we
// want to transport the type role, this is because the display role
// is derived from the type role.
QMap<int, QVariant> DecodeHighlightingModel::itemData (QModelIndex const& index) const
{
auto roles = QAbstractListModel::itemData (index);
QVariant variantData = data (index, TypeRole);
if (variantData.isValid ())
{
roles.insert (TypeRole, variantData);
}
return roles;
}
QVariant DecodeHighlightingModel::headerData (int /*section*/, Qt::Orientation orientation, int role) const
{
QVariant header;
if (Qt::DisplayRole == role && Qt::Horizontal == orientation)
{
header = tr ("Highlight Type");
}
return header;
}
Qt::ItemFlags DecodeHighlightingModel::flags (QModelIndex const& index) const
{
auto flags = QAbstractListModel::flags (index) | Qt::ItemIsDragEnabled;
if (index.isValid ())
{
flags |= Qt::ItemIsUserCheckable;
}
else
{
flags |= Qt::ItemIsDropEnabled;
}
return flags;
}
bool DecodeHighlightingModel::setData (QModelIndex const& index, QVariant const& value, int role)
{
bool ok {false};
if (index.isValid () && index.row () < rowCount ())
{
auto& item = m_->data_[index.row ()];
QVector<int> roles;
roles << role;
switch (role)
{
case Qt::DisplayRole:
case Qt::FontRole:
ok = true;
break;
case Qt::CheckStateRole:
if (item.enabled_ != (Qt::Checked == value))
{
item.enabled_ = Qt::Checked == value;
Q_EMIT dataChanged (index, index, roles);
}
ok = true;
break;
case Qt::ForegroundRole:
if (item.foreground_ != value.value<QBrush> ())
{
item.foreground_ = value.value<QBrush> ();
Q_EMIT dataChanged (index, index, roles);
}
ok = true;
break;
case Qt::BackgroundRole:
if (item.background_ != value.value<QBrush> ())
{
item.background_ = value.value<QBrush> ();
Q_EMIT dataChanged (index, index, roles);
}
ok = true;
break;
case TypeRole:
if (item.type_ != static_cast<Highlight> (value.toInt ()))
{
item.type_ = static_cast<Highlight> (value.toInt ());
roles << Qt::DisplayRole;
Q_EMIT dataChanged (index, index, roles);
}
ok = true;
break;
}
}
return ok;
}
Qt::DropActions DecodeHighlightingModel::supportedDropActions () const
{
return Qt::MoveAction;
}
bool DecodeHighlightingModel::insertRows (int row, int count, QModelIndex const& parent)
{
beginInsertRows (parent, row, row + count - 1);
for (int index = 0; index < count; ++index)
{
m_->data_.insert (row, HighlightInfo {Highlight::CQ, false, {}, {}});
}
endInsertRows ();
return true;
}
bool DecodeHighlightingModel::removeRows (int row, int count, QModelIndex const& parent)
{
beginRemoveRows (parent, row, row + count - 1);
for (int index = 0; index < count; ++index)
{
m_->data_.removeAt (row);
}
endRemoveRows ();
return true;
}

View File

@ -0,0 +1,77 @@
#ifndef DECODE_HIGHLIGHTING_MODEL_HPP_
#define DECODE_HIGHLIGHTING_MODEL_HPP_
#include <QAbstractListModel>
#include <QBrush>
#include <QList>
#include "qt_helpers.hpp"
#include "pimpl_h.hpp"
class QObject;
class QFont;
class QDataStream;
class QDebug;
class DecodeHighlightingModel final
: public QAbstractListModel
{
Q_OBJECT
public:
enum class Highlight : char {CQ, MyCall, Tx, DXCC, DXCCBand, Grid, GridBand, Call, CallBand, LotW};
Q_ENUM (Highlight)
static QString highlight_name (Highlight h);
struct HighlightInfo final
{
Highlight type_;
bool enabled_;
QBrush foreground_;
QBrush background_;
};
using HighlightItems = QList<HighlightInfo>;
explicit DecodeHighlightingModel (QObject * parent = 0);
~DecodeHighlightingModel();
// access to raw items nd default items
static HighlightItems const& default_items ();
HighlightItems const& items () const;
void items (HighlightItems const&);
void set_font (QFont const&);
enum DefaultRoles {TypeRole = Qt::UserRole, EnabledDefaultRole, ForegroundDefaultRole, BackgroundDefaultRole};
private:
// implement the QAbstractListModel interface
int rowCount (QModelIndex const& parent = QModelIndex()) const override;
QVariant data (QModelIndex const&, int role) const override;
QVariant headerData (int section, Qt::Orientation, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags (QModelIndex const&) const override;
bool setData (QModelIndex const& index, QVariant const& value, int role) override;
Qt::DropActions supportedDropActions () const override;
bool insertRows (int row, int count, QModelIndex const& parent = QModelIndex {}) override;
bool removeRows (int row, int count, QModelIndex const& parent = QModelIndex {}) override;
QMap<int, QVariant> itemData (QModelIndex const&) const override;
class impl;
pimpl<impl> m_;
};
bool operator == (DecodeHighlightingModel::HighlightInfo const&, DecodeHighlightingModel::HighlightInfo const&);
QDataStream& operator << (QDataStream&, DecodeHighlightingModel::HighlightInfo const&);
QDataStream& operator >> (QDataStream&, DecodeHighlightingModel::HighlightInfo&);
#if !defined (QT_NO_DEBUG_STREAM)
QDebug operator << (QDebug, DecodeHighlightingModel::HighlightInfo const&);
#endif
ENUM_QDATASTREAM_OPS_DECL (DecodeHighlightingModel, Highlight);
ENUM_CONVERSION_OPS_DECL (DecodeHighlightingModel, Highlight);
Q_DECLARE_METATYPE (DecodeHighlightingModel::HighlightInfo);
Q_DECLARE_METATYPE (DecodeHighlightingModel::HighlightItems);
#endif

View File

@ -1,11 +1,14 @@
#include "ExportCabrillo.h" #include "ExportCabrillo.h"
#include "ui_exportCabrillo.h"
#include "SettingsGroup.hpp" #include "SettingsGroup.hpp"
#include "MessageBox.hpp"
#include <QApplication> #include <QApplication>
#include <QDebug> #include <QDebug>
#include <QFileDialog> #include <QFileDialog>
#include "ui_ExportCabrillo.h"
#include "moc_ExportCabrillo.cpp"
ExportCabrillo::ExportCabrillo(QSettings *settings, QWidget *parent) : ExportCabrillo::ExportCabrillo(QSettings *settings, QWidget *parent) :
QDialog(parent), QDialog(parent),
settings_ {settings}, settings_ {settings},
@ -18,27 +21,106 @@ ExportCabrillo::ExportCabrillo(QSettings *settings, QWidget *parent) :
ExportCabrillo::~ExportCabrillo() ExportCabrillo::~ExportCabrillo()
{ {
if (isVisible ()) write_settings(); if(isVisible()) write_settings();
delete ui; delete ui;
} }
void ExportCabrillo::closeEvent (QCloseEvent * e)
{
write_settings();
QWidget::closeEvent(e);
}
void ExportCabrillo::read_settings () void ExportCabrillo::read_settings ()
{ {
SettingsGroup group {settings_, "ExportCabrillo"}; SettingsGroup group {settings_, "ExportCabrillo"};
restoreGeometry (settings_->value ("window/geometry").toByteArray ()); restoreGeometry (settings_->value("window/geometry").toByteArray());
ui->lineEdit_1->setText(settings_->value("Location").toString());
ui->lineEdit_2->setText(settings_->value("Contest").toString());
ui->lineEdit_3->setText(settings_->value("Callsign").toString());
ui->lineEdit_4->setText(settings_->value("Category-Operator").toString());
ui->lineEdit_5->setText(settings_->value("Category-Transmitter").toString());
ui->lineEdit_6->setText(settings_->value("Category-Power").toString());
ui->lineEdit_7->setText(settings_->value("Category-Assisted").toString());
ui->lineEdit_8->setText(settings_->value("Category-Band").toString());
ui->lineEdit_9->setText(settings_->value("Claimed-Score").toString());
ui->lineEdit_10->setText(settings_->value("Operators").toString());
ui->lineEdit_11->setText(settings_->value("Club").toString());
ui->lineEdit_12->setText(settings_->value("Name").toString());
ui->lineEdit_13->setText(settings_->value("Address1").toString());
ui->lineEdit_14->setText(settings_->value("Address2").toString());
} }
void ExportCabrillo::write_settings () void ExportCabrillo::write_settings ()
{ {
SettingsGroup group {settings_, "ExportCabrillo"}; SettingsGroup group {settings_, "ExportCabrillo"};
settings_->setValue ("window/geometry", saveGeometry ()); settings_->setValue ("window/geometry", saveGeometry ());
settings_->setValue("Location",ui->lineEdit_1->text());
settings_->setValue("Contest",ui->lineEdit_2->text());
settings_->setValue("Callsign",ui->lineEdit_3->text());
settings_->setValue("Category-Operator",ui->lineEdit_4->text());
settings_->setValue("Category-Transmitter",ui->lineEdit_5->text());
settings_->setValue("Category-Power",ui->lineEdit_6->text());
settings_->setValue("Category-Assisted",ui->lineEdit_7->text());
settings_->setValue("Category-Band",ui->lineEdit_8->text());
settings_->setValue("Claimed-Score",ui->lineEdit_9->text());
settings_->setValue("Operators",ui->lineEdit_10->text());
settings_->setValue("Club",ui->lineEdit_11->text());
settings_->setValue("Name",ui->lineEdit_12->text());
settings_->setValue("Address1",ui->lineEdit_13->text());
settings_->setValue("Address2",ui->lineEdit_14->text());
} }
void ExportCabrillo::setFile(QString t)
{
m_CabLog=t;
}
void ExportCabrillo::on_pbSaveAs_clicked() void ExportCabrillo::on_pbSaveAs_clicked()
{ {
QString fname; QString fname;
QFileDialog saveAs(this); QFileDialog saveAs(this);
saveAs.setFileMode(QFileDialog::AnyFile); saveAs.setFileMode(QFileDialog::AnyFile);
fname=saveAs.getSaveFileName(this, "Save File", "","Cabrillo Log (*.log)"); fname=saveAs.getSaveFileName(this, "Save File", "","Cabrillo Log (*.log)");
qDebug() << "AA" << fname; QFile f {fname};
if (f.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&f);
out << "START-OF-LOG:3.0" << endl
<< "LOCATION: " << ui->lineEdit_1->text() << endl
<< "CONTEST: " << ui->lineEdit_2->text() << endl
<< "CALLSIGN: " << ui->lineEdit_3->text() << endl
<< "CATEGORY-OPERATOR: " << ui->lineEdit_4->text() << endl
<< "CATEGORY-TRANSMITTER: " << ui->lineEdit_5->text() << endl
<< "CATEGORY-POWER: " << ui->lineEdit_6->text() << endl
<< "CATEGORY-ASSISTED: " << ui->lineEdit_7->text() << endl
<< "CATEGORY-BAND: " << ui->lineEdit_8->text() << endl
<< "CLAIMED-SCORE: " << ui->lineEdit_9->text() << endl
<< "OPERATORS: " << ui->lineEdit_10->text() << endl
<< "CLUB: " << ui->lineEdit_11->text() << endl
<< "NAME: " << ui->lineEdit_12->text() << endl
<< "ADDRESS: " << ui->lineEdit_13->text() << endl
<< "ADDRESS: " << ui->lineEdit_14->text() << endl;
QFile f2(m_CabLog);
if(f2.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream s(&f2);
QString t=s.readAll();
out << t << "END-OF-LOG:" << endl;
f2.close();
}
f.close();
} else {
auto const& message = tr ("Cannot open \"%1\" for writing: %2")
.arg (f.fileName ()).arg (f.errorString ());
MessageBox::warning_message (this, tr ("Export Cabrillo File Error"), message);
}
write_settings();
}
void ExportCabrillo::accept()
{
write_settings();
QDialog::accept();
} }

View File

@ -14,13 +14,21 @@ class ExportCabrillo : public QDialog
public: public:
explicit ExportCabrillo(QSettings *settings, QWidget *parent = 0); explicit ExportCabrillo(QSettings *settings, QWidget *parent = 0);
void setFile(QString t);
~ExportCabrillo(); ~ExportCabrillo();
public slots:
void accept();
protected:
void closeEvent (QCloseEvent *) override;
private slots: private slots:
void on_pbSaveAs_clicked(); void on_pbSaveAs_clicked();
private: private:
QSettings * settings_; QSettings * settings_;
QString m_CabLog;
void read_settings(); void read_settings();
void write_settings(); void write_settings();
Ui::ExportCabrillo *ui; Ui::ExportCabrillo *ui;

View File

@ -17,14 +17,14 @@
<item row="0" column="0" colspan="2"> <item row="0" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="label_1">
<property name="text"> <property name="text">
<string>Location:</string> <string>Location:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLineEdit" name="lineEdit"> <widget class="QLineEdit" name="lineEdit_1">
<property name="text"> <property name="text">
<string>SNJ</string> <string>SNJ</string>
</property> </property>

View File

@ -261,12 +261,7 @@ HamlibTransceiver::HamlibTransceiver (int model_number, TransceiverFactory::Para
// //
// user defined Hamlib settings // user defined Hamlib settings
// //
auto settings_file_name = QStandardPaths::locate ( auto settings_file_name = QStandardPaths::locate (QStandardPaths::AppConfigLocation
#if QT_VERSION >= 0x050500
QStandardPaths::AppConfigLocation
#else
QStandardPaths::ConfigLocation
#endif
, "hamlib_settings.json"); , "hamlib_settings.json");
if (!settings_file_name.isEmpty ()) if (!settings_file_name.isEmpty ())
{ {

View File

@ -47,7 +47,7 @@ protected:
void stepBy (int steps) override; void stepBy (int steps) override;
private: private:
std::vector<int> values_; values_type values_;
}; };
#endif #endif

View File

@ -92,9 +92,5 @@ QVariant IARURegions::headerData (int section, Qt::Orientation orientation, int
return result; return result;
} }
#if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_IMPL (IARURegions, Region);
#endif
ENUM_QDATASTREAM_OPS_IMPL (IARURegions, Region); ENUM_QDATASTREAM_OPS_IMPL (IARURegions, Region);
ENUM_CONVERSION_OPS_IMPL (IARURegions, Region); ENUM_CONVERSION_OPS_IMPL (IARURegions, Region);

View File

@ -29,8 +29,6 @@ class IARURegions final
: public QAbstractListModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
Q_ENUMS (Region)
public: public:
// //
// This enumeration contains the supported regions, to complement // This enumeration contains the supported regions, to complement
@ -62,19 +60,6 @@ public:
QVariant headerData (int section, Qt::Orientation, int = Qt::DisplayRole) const override; QVariant headerData (int section, Qt::Orientation, int = Qt::DisplayRole) const override;
}; };
// Qt boilerplate to make the IARURegions::region enumeration a type
// that can be streamed and queued as a signal argument as well as
// showing the human readable string when output to debug streams.
#if QT_VERSION < 0x050500
// Qt 5.5 introduces the Q_ENUM macro which automatically registers
// the meta-type
Q_DECLARE_METATYPE (IARURegions::Region);
#endif
#if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_DECL (IARURegions, Region);
#endif
ENUM_QDATASTREAM_OPS_DECL (IARURegions, Region); ENUM_QDATASTREAM_OPS_DECL (IARURegions, Region);
ENUM_CONVERSION_OPS_DECL (IARURegions, Region); ENUM_CONVERSION_OPS_DECL (IARURegions, Region);

280
LotWUsers.cpp Normal file
View File

@ -0,0 +1,280 @@
#include "LotWUsers.hpp"
#include <future>
#include <QHash>
#include <QString>
#include <QDate>
#include <QFile>
#include <QTextStream>
#include <QDir>
#include <QFileInfo>
#include <QPointer>
#include <QSaveFile>
#include <QUrl>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QDebug>
#include "pimpl_impl.hpp"
#include "moc_LotWUsers.cpp"
namespace
{
// Dictionary mapping call sign to date of last upload to LotW
using dictionary = QHash<QString, QDate>;
}
class LotWUsers::impl final
: public QObject
{
Q_OBJECT
public:
impl (LotWUsers * self, QNetworkAccessManager * network_manager)
: self_ {self}
, network_manager_ {network_manager}
, url_valid_ {false}
, redirect_count_ {0}
, age_constraint_ {365}
{
}
void load (QString const& url, bool forced_fetch)
{
auto csv_file_name = csv_file_.fileName ();
abort (); // abort any active download
if (!QFileInfo::exists (csv_file_name) || forced_fetch)
{
current_url_.setUrl (url);
redirect_count_ = 0;
download (current_url_);
}
else
{
// load the database asynchronously
future_load_ = std::async (std::launch::async, &LotWUsers::impl::load_dictionary, this, csv_file_name);
}
}
void download (QUrl url)
{
if (QNetworkAccessManager::Accessible != network_manager_->networkAccessible ())
{
// try and recover network access for QNAM
network_manager_->setNetworkAccessible (QNetworkAccessManager::Accessible);
}
if (url.isValid () && !QSslSocket::supportsSsl ())
{
url.setScheme ("http");
}
QNetworkRequest request {url};
request.setRawHeader ("User-Agent", "WSJT LotW User Downloader");
request.setOriginatingObject (this);
// this blocks for a second or two the first time it is used on
// Windows - annoying
if (!url_valid_)
{
reply_ = network_manager_->head (request);
}
else
{
reply_ = network_manager_->get (request);
}
connect (reply_.data (), &QNetworkReply::finished, this, &LotWUsers::impl::reply_finished);
connect (reply_.data (), &QNetworkReply::readyRead, this, &LotWUsers::impl::store);
}
void reply_finished ()
{
if (!reply_)
{
Q_EMIT self_->load_finished ();
return; // we probably deleted it in an earlier call
}
QUrl redirect_url {reply_->attribute (QNetworkRequest::RedirectionTargetAttribute).toUrl ()};
if (reply_->error () == QNetworkReply::NoError && !redirect_url.isEmpty ())
{
if (++redirect_count_ < 10) // maintain sanity
{
// follow redirect
download (reply_->url ().resolved (redirect_url));
}
else
{
Q_EMIT self_->LotW_users_error (tr ("Network Error - Too many redirects:\n\'%1\'")
.arg (redirect_url.toDisplayString ()));
url_valid_ = false; // reset
Q_EMIT self_->load_finished ();
}
}
else if (reply_->error () != QNetworkReply::NoError)
{
csv_file_.cancelWriting ();
csv_file_.commit ();
url_valid_ = false; // reset
// report errors that are not due to abort
if (QNetworkReply::OperationCanceledError != reply_->error ())
{
Q_EMIT self_->LotW_users_error (tr ("Network Error:\n%1")
.arg (reply_->errorString ()));
}
Q_EMIT self_->load_finished ();
}
else
{
if (url_valid_ && !csv_file_.commit ())
{
Q_EMIT self_->LotW_users_error (tr ("File System Error - Cannot commit changes to:\n\"%1\"")
.arg (csv_file_.fileName ()));
url_valid_ = false; // reset
Q_EMIT self_->load_finished ();
}
else
{
if (!url_valid_)
{
// now get the body content
url_valid_ = true;
download (reply_->url ().resolved (redirect_url));
}
else
{
url_valid_ = false; // reset
// load the database asynchronously
future_load_ = std::async (std::launch::async, &LotWUsers::impl::load_dictionary, this, csv_file_.fileName ());
}
}
}
if (reply_ && reply_->isFinished ())
{
reply_->deleteLater ();
}
}
void store ()
{
if (url_valid_)
{
if (!csv_file_.isOpen ())
{
// create temporary file in the final location
if (!csv_file_.open (QSaveFile::WriteOnly))
{
abort ();
Q_EMIT self_->LotW_users_error (tr ("File System Error - Cannot open file:\n\"%1\"\nError(%2): %3")
.arg (csv_file_.fileName ())
.arg (csv_file_.error ())
.arg (csv_file_.errorString ()));
}
}
if (csv_file_.write (reply_->read (reply_->bytesAvailable ())) < 0)
{
abort ();
Q_EMIT self_->LotW_users_error (tr ("File System Error - Cannot write to file:\n\"%1\"\nError(%2): %3")
.arg (csv_file_.fileName ())
.arg (csv_file_.error ())
.arg (csv_file_.errorString ()));
}
}
}
void abort ()
{
if (reply_ && reply_->isRunning ())
{
reply_->abort ();
}
}
// Load the database from the given file name
//
// Expects the file to be in CSV format with no header with one
// record per line. Record fields are call sign followed by upload
// date in yyyy-MM-dd format followed by upload time (ignored)
dictionary load_dictionary (QString const& lotw_csv_file)
{
dictionary result;
QFile f {lotw_csv_file};
if (f.open (QFile::ReadOnly | QFile::Text))
{
QTextStream s {&f};
for (auto l = s.readLine (); !l.isNull (); l = s.readLine ())
{
auto pos = l.indexOf (',');
result[l.left (pos)] = QDate::fromString (l.mid (pos + 1, l.indexOf (',', pos + 1) - pos - 1), "yyyy-MM-dd");
}
// qDebug () << "LotW User Data Loaded";
}
else
{
throw std::runtime_error {QObject::tr ("Failed to open LotW users CSV file: '%1'").arg (f.fileName ()).toStdString ()};
}
return result;
}
LotWUsers * self_;
QNetworkAccessManager * network_manager_;
QSaveFile csv_file_;
bool url_valid_;
QUrl current_url_; // may be a redirect
int redirect_count_;
QPointer<QNetworkReply> reply_;
std::future<dictionary> future_load_;
dictionary last_uploaded_;
qint64 age_constraint_; // days
};
#include "LotWUsers.moc"
LotWUsers::LotWUsers (QNetworkAccessManager * network_manager, QObject * parent)
: QObject {parent}
, m_ {this, network_manager}
{
}
LotWUsers::~LotWUsers ()
{
}
void LotWUsers::set_local_file_path (QString const& path)
{
m_->csv_file_.setFileName (path);
}
void LotWUsers::load (QString const& url, bool force_download)
{
m_->load (url, force_download);
}
void LotWUsers::set_age_constraint (qint64 uploaded_since_days)
{
m_->age_constraint_ = uploaded_since_days;
}
bool LotWUsers::user (QString const& call) const
{
if (m_->future_load_.valid ())
{
try
{
// wait for the load to finish if necessary
const_cast<dictionary&> (m_->last_uploaded_) = const_cast<std::future<dictionary>&> (m_->future_load_).get ();
}
catch (std::exception const& e)
{
Q_EMIT LotW_users_error (e.what ());
}
Q_EMIT load_finished ();
}
auto p = m_->last_uploaded_.constFind (call);
if (p != m_->last_uploaded_.end ())
{
return p.value ().daysTo (QDate::currentDate ()) <= m_->age_constraint_;
}
return false;
}

41
LotWUsers.hpp Normal file
View File

@ -0,0 +1,41 @@
#ifndef LOTW_USERS_HPP_
#define LOTW_USERS_HPP_
#include <boost/core/noncopyable.hpp>
#include <QObject>
#include "pimpl_h.hpp"
class QString;
class QDate;
class QNetworkAccessManager;
//
// LotWUsers - Lookup Logbook of the World users
//
class LotWUsers final
: public QObject
{
Q_OBJECT
public:
explicit LotWUsers (QNetworkAccessManager *, QObject * parent = 0);
~LotWUsers ();
void set_local_file_path (QString const&);
Q_SLOT void load (QString const& url, bool force_download = false);
Q_SLOT void set_age_constraint (qint64 uploaded_since_days);
// returns true if the specified call sign 'call' has uploaded their
// log to LotW in the last 'age_constraint_days' days
bool user (QString const& call) const;
Q_SIGNAL void LotW_users_error (QString const& reason) const;
Q_SIGNAL void load_finished () const;
private:
class impl;
pimpl<impl> m_;
};
#endif

View File

@ -334,7 +334,7 @@ MessageClient::MessageClient (QString const& id, QString const& version, QString
connect (&*m_, static_cast<void (impl::*) (impl::SocketError)> (&impl::error) connect (&*m_, static_cast<void (impl::*) (impl::SocketError)> (&impl::error)
, [this] (impl::SocketError e) , [this] (impl::SocketError e)
{ {
#if defined (Q_OS_WIN) && QT_VERSION >= 0x050500 #if defined (Q_OS_WIN)
if (e != impl::NetworkError // take this out when Qt 5.5 if (e != impl::NetworkError // take this out when Qt 5.5
// stops doing this // stops doing this
// spuriously // spuriously

View File

@ -13,7 +13,7 @@
#include "TransceiverFactory.hpp" #include "TransceiverFactory.hpp"
#include "WFPalette.hpp" #include "WFPalette.hpp"
#include "IARURegions.hpp" #include "IARURegions.hpp"
#include "DecodeHighlightingModel.hpp"
#include "FrequencyLineEdit.hpp" #include "FrequencyLineEdit.hpp"
QItemEditorFactory * item_editor_factory () QItemEditorFactory * item_editor_factory ()
@ -47,10 +47,6 @@ void register_types ()
qRegisterMetaType<AudioDevice::Channel> ("AudioDevice::Channel"); qRegisterMetaType<AudioDevice::Channel> ("AudioDevice::Channel");
// Configuration // Configuration
#if QT_VERSION < 0x050500
qRegisterMetaType<Configuration::DataMode> ("Configuration::DataMode");
qRegisterMetaType<Configuration::Type2MsgGen> ("Configuration::Type2MsgGen");
#endif
qRegisterMetaTypeStreamOperators<Configuration::DataMode> ("Configuration::DataMode"); qRegisterMetaTypeStreamOperators<Configuration::DataMode> ("Configuration::DataMode");
qRegisterMetaTypeStreamOperators<Configuration::Type2MsgGen> ("Configuration::Type2MsgGen"); qRegisterMetaTypeStreamOperators<Configuration::Type2MsgGen> ("Configuration::Type2MsgGen");
@ -62,17 +58,8 @@ void register_types ()
// Transceiver // Transceiver
qRegisterMetaType<Transceiver::TransceiverState> ("Transceiver::TransceiverState"); qRegisterMetaType<Transceiver::TransceiverState> ("Transceiver::TransceiverState");
qRegisterMetaType<Transceiver::MODE> ("Transceiver::MODE");
// Transceiver factory // Transceiver factory
#if QT_VERSION < 0x050500
qRegisterMetaType<TransceiverFactory::DataBits> ("TransceiverFactory::DataBits");
qRegisterMetaType<TransceiverFactory::StopBits> ("TransceiverFactory::StopBits");
qRegisterMetaType<TransceiverFactory::Handshake> ("TransceiverFactory::Handshake");
qRegisterMetaType<TransceiverFactory::PTTMethod> ("TransceiverFactory::PTTMethod");
qRegisterMetaType<TransceiverFactory::TXAudioSource> ("TransceiverFactory::TXAudioSource");
qRegisterMetaType<TransceiverFactory::SplitMode> ("TransceiverFactory::SplitMode");
#endif
qRegisterMetaTypeStreamOperators<TransceiverFactory::DataBits> ("TransceiverFactory::DataBits"); qRegisterMetaTypeStreamOperators<TransceiverFactory::DataBits> ("TransceiverFactory::DataBits");
qRegisterMetaTypeStreamOperators<TransceiverFactory::StopBits> ("TransceiverFactory::StopBits"); qRegisterMetaTypeStreamOperators<TransceiverFactory::StopBits> ("TransceiverFactory::StopBits");
qRegisterMetaTypeStreamOperators<TransceiverFactory::Handshake> ("TransceiverFactory::Handshake"); qRegisterMetaTypeStreamOperators<TransceiverFactory::Handshake> ("TransceiverFactory::Handshake");
@ -84,8 +71,9 @@ void register_types ()
qRegisterMetaTypeStreamOperators<WFPalette::Colours> ("Colours"); qRegisterMetaTypeStreamOperators<WFPalette::Colours> ("Colours");
// IARURegions // IARURegions
#if QT_VERSION < 0x050500
qRegisterMetaType<IARURegions::Region> ("IARURegions::Region");
#endif
qRegisterMetaTypeStreamOperators<IARURegions::Region> ("IARURegions::Region"); qRegisterMetaTypeStreamOperators<IARURegions::Region> ("IARURegions::Region");
// DecodeHighlightingModel
qRegisterMetaTypeStreamOperators<DecodeHighlightingModel::HighlightInfo> ("HighlightInfo");
qRegisterMetaTypeStreamOperators<DecodeHighlightingModel::HighlightItems> ("HighlightItems");
} }

View File

@ -98,9 +98,5 @@ QVariant Modes::headerData (int section, Qt::Orientation orientation, int role)
return result; return result;
} }
#if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_IMPL (Modes, Mode);
#endif
ENUM_QDATASTREAM_OPS_IMPL (Modes, Mode); ENUM_QDATASTREAM_OPS_IMPL (Modes, Mode);
ENUM_CONVERSION_OPS_IMPL (Modes, Mode); ENUM_CONVERSION_OPS_IMPL (Modes, Mode);

View File

@ -29,7 +29,6 @@ class Modes final
: public QAbstractListModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
Q_ENUMS (Mode)
public: public:
// //
@ -69,19 +68,6 @@ public:
QVariant headerData (int section, Qt::Orientation, int = Qt::DisplayRole) const override; QVariant headerData (int section, Qt::Orientation, int = Qt::DisplayRole) const override;
}; };
// Qt boilerplate to make the Modes::Mode enumeration a type that can
// be streamed and queued as a signal argument as well as showing the
// human readable string when output to debug streams.
#if QT_VERSION < 0x050500
// Qt 5.5 introduces the Q_ENUM macro which automatically registers
// the meta-type
Q_DECLARE_METATYPE (Modes::Mode);
#endif
#if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_DECL (Modes, Mode);
#endif
ENUM_QDATASTREAM_OPS_DECL (Modes, Mode); ENUM_QDATASTREAM_OPS_DECL (Modes, Mode);
ENUM_CONVERSION_OPS_DECL (Modes, Mode); ENUM_CONVERSION_OPS_DECL (Modes, Mode);

View File

@ -1,2 +1,471 @@
The content of this file has been moved to the NEWS file, please add __ __ ______ _____ ________ __ __
release note updates to that file. | \ _ | \ / \ | \| \ | \ | \
| $$ / \ | $$| $$$$$$\ \$$$$$ \$$$$$$$$ | $$ | $$
| $$/ $\| $$| $$___\$$ | $$ | $$ ______ \$$\/ $$
| $$ $$$\ $$ \$$ \ __ | $$ | $$| \ >$$ $$
| $$ $$\$$\$$ _\$$$$$$\| \ | $$ | $$ \$$$$$$/ $$$$\
| $$$$ \$$$$| \__| $$| $$__| $$ | $$ | $$ \$$\
| $$$ \$$$ \$$ $$ \$$ $$ | $$ | $$ | $$
\$$ \$$ \$$$$$$ \$$$$$$ \$$ \$$ \$$
Copyright 2001 - 2018 by Joe Taylor, K1JT.
Release: WSJT-X 2.0-rc3
October 15, 2018
-----------------------
Changes from WSJT-X Version 2.0.0-rc1 include the following:
- Improved SNR calculation for FT8
- Test grid4 (not grid6) for matches in ADIF log
- Auto-generate 77-bit messages for callsigns with /R or /P
- Fix auto-sequencing for "CQ ABC ...", "CQ ABCD ...", etc.
- Fix the "CQ RU RU ..." bug
- Implement AP decoding for contest messages and for Hound
- Check Field Day and RTTY Roundup exchanges for validity
- Implement "Select next caller" and use of "TU; ..." messages
- Option to "auto log" in contests
- Real-time display of contest log
- Contest exchanges sent to ADIF log and N1MM+
- Function to export Cabrillo log
- Convert DXpedition mode to always use 77-bit messages
- Fix bug associated with opening "houndcallers.txt"
- Remove end-of-line numbers from MSK144 decodes
- Finish MSK144 encoding/decoding for Sh msgs and nonstandard calls
- Halt Tx before resetting power after Tune
- Auto update of LoTW info, and faster program startup
Release: WSJT-X 2.0-rc2
September 25, 2018
-----------------------
Changes from WSJT-X Version 2.0.0-rc1 include the following:
- Corrected a flaw that encoded a message's first callsign as
hexadecimal telemetry data if the call consisted only of letters
A-F and digits 0-9.
- Corrected program logic that failed to identify certain callsigns
as "nonstandard".
- Fixed a bug that color-highlighted bare CQ messages (no grid
locator) as "New DXCC".
- Fixed a bug that failed to log Report Sent if MyCall is a
nonstandard call.
- Fixed a bug that generated incorrect MSK144 tones for certain
messages and caused a "memory" effect on stations receiving the
incorrect tones.
- Fixed several bugs that could cause certain Tx messages to crash
the program.
- Suppressed the display of certain illogical false decodes.
Release: WSJT-X 2.0-rc1
September 17, 2018
-----------------------
This is the first candidate release on WSJT-X 2.0, intended for
beta-level testing. For details see:
http://physics.princeton.edu/pulsar/k1jt/New_Features_WSJT-X_2.0.txt
http://physics.princeton.edu/pulsar/k1jt/Quick_Start_WSJT-X_2.0.pdf
http://physics.princeton.edu/pulsar/k1jt/77bit.txt
Release: WSJT-X Version 1.9.1
May 31, 2018
-----------------------------
This release is a critical bug fix release that removes an unintended
restriction of FT8 DXpedition mode.
Release: WSJT-X Version 1.9.0
May 28, 2018
-----------------------------
Changes from WSJT-X Version 1.9.0-rc4 include the following:
- Display in the right text window of MSK144 messages addressed to
"MyCall" has been restored.
- Fox is not allowed to transmit in any of the default FT8 sub-bands.
- Fox can now work Hounds using compound callsigns.
- Fox can now transmit free-text messages (and any standard FT8 message)
by using Tab 1 or Tab 2.
- Added a checkbox to enable more frequent programmed CQs by Fox.
Default is OFF.
- Alt+N keyboard shortcut has been restored.
- MacOS program crash on unexpected decode request has been fixed.
- Several minor bug fixes and added convenience features.
- Hamlib, support for TRXManger added.
- Hamlib, improved support for flrig.
Release: WSJT-X Version 1.9.0-rc4
April 30, 2018
---------------------------------
Changes from WSJT-X Version 1.9.0-rc3 include the following:
- Corrected a number of flaws in Fox and Hound behavior, FT8
DXpedition Mode
- Decoded CQ calls where a prefix has been used as a suffix should
have the DXCC entity name assigned correctly in almost all cases
- Improved AFC capability for the wider JT65 sub-modes to help with
drifting signals
- Better support for macOS using hi-DPI Retina displays
- New UDP message that allows external applications to highlight
decoded callsigns
- Main-screen geometry and state of the "splitter" setting between its
two text windows is now properly restored after program restart.
- New simulator jt49sim[.exe] replaces jt4sim and jt9sim
- Correct S/N measurements for the JT9 slow/wide submodes
- Other minor bug fixes
- Updated copy of cty.dat
Release: WSJT-X Version 1.9.0-rc3
March 18, 2018
---------------------------------
Changes from WSJT-X Version 1.9.0-rc2 include the following:
- Corrected a number of flaws in Fox behavior, FT8 DXpedition Mode
- Allow Hounds to use compound callsigns
- Write debugging information to FoxQSO.txt.
- Fix the "Blue Decode Button" bug
- Allow partial processing of incoming UDP Reply messages so that
non-CQ/QRZ decodes can be processed. The processing is the same as
double-clicking the same decoded message within WSJT-X except that
"Enable Tx" will not be enabled.
- Send DX grid locator to wsjt_status.txt, for use by applications like
PstRotatorAZ
- Correct the display of DXCC status of KG4 calls
- Updated copy of cty.dat
- Updates to documentation
- Other minor bug fixes
- This release contains updated Hamlib functionality including changes
to the Yaesu FT-817 back end that allows the uBITx kit transceiver
to be CAT controlled by WSJT-X.
Release: WSJT-X Version 1.9.0-rc2
February 26, 2018
---------------------------------
Changes from WSJT-X Version 1.8.0 include the following:
- New FT8 DXpedition Mode to facilitate high QSO rates in pileup
situations
- Decoding improvements for JT65 mode, including a priori (AP)
decoding when VHF/UHF/Microwave features are enabled
- Optional Auto-Sequencing in JT4, JT9, and JT65 when
VHF/UHF/Microwave features are enabled
- Better suppression of low-confidence false decodes generated by AP
decoding in FT8 mode
- Improved decoding performance for WSPR mode, especially effective at
LF and MF
- Minor adjustments to auto-sequencing behavior
- More flexible Doppler control features for EME
- Improved waterfall sensitivity for very weak signals
- Automatic real-time forwarding of logged information to N1MM Logger+
- Expanded and improved UDP messages sent to companion programs
- Bug fixes and other minor tweaks to user interface
A primary purpose of this beta release is to allow field testing of
FT8 DXpedition Mode. Instructions for this mode are posted here:
http://physics.princeton.edu/pulsar/k1jt/FT8_DXpedition_Mode.pdf
Contacts in FT8 DXpedition Mode must use WSJT-X v1.9.0 at both ends of
the QSO. Please report any anomalous behavior to email list
wsjt-devel@lists.sourceforge.net. You must be a subscriber in order
to post there.
Release: WSJT-X Version 1.8.0
October 27, 2017
-----------------------------
This is the full General Availability release of WSJT-X Version 1.8.0.
Changes from WSJT-X Version 1.8.0-rc3 are very minor:
- Right-click on the Wide Graph now pops up a Context Menu. Select
the item *Set Rx & Tx Offset* to complete a one-handed setting of
both red and green frequency markers.
- Several clarifications and additions to Tool Tips and the User Guide.
We recommend that all users should upgrade to WSJT-X Version 1.8.0.
If you upgrade from v1.8.0-rc1 it may be necessary to do a one-time
reset of the default list of suggested operating frequencies. Go to
*File->Settings->Frequencies*, right click on the table and select
*Reset*.
Release: WSJT-X Version 1.8.0-rc3
October 16, 2017
---------------------------------
Most (but not all) changes since Version 1.8.0-rc2 involve user
control of the increasingly popular FT8 mode. The "RC3" release also
includes minor bug fixes and updates to the WSJT-X User Guide.
The following list includes all of the more important changes:
- New optimization of GUI for simplex and split behavior in FT8 mode.
1. Checkbox "Lock Tx Freq" on main window is relabeled "Hold Tx Freq".
2. Double-clicking on decoded messages that do not contain your own
call moves both Rx and Tx frequencies. If the first callsign is
your own call, only Rx freq moves.
3. Double-clicking on decoded messages moves the Rx frequency. If
"Hold Tx Freq" is checked, Tx frequency is moved only if CTRL was
held down.
4. Clicking on the waterfall moves Rx and Tx frequencies as
before: Rx only on a simple click, Tx only on SHIFT-click, and
both on CTRL-click. This happens even if "Hold Tx Freq" is
checked.
- Add a semi-automated "FreqCal" procedure: see *Solve for calibration
parameters* on the Tools menu.
- Improv auto-sequencing behavior: stop and on-frequency
transmission if a called station comes back to someone else.
- Improve S/N estimation in some situations involving QRM.
- Fix an initialization issue with user-modified application fonts.
- Fix an issue with Tx5 message generation with Type 2 compound calls.
- Enhance and improve the ADIF parser of logbook records. Update
the band limits as per ADIF 3.0.6 specification.
- Increase the FT8 DT range to +/- 2.5 s.
- Do not allow window manager events to close the astronomical data
window.
- Add an "Erase" item to the context (right-click) menu for decoded
text.
- Extend UDP messages with an "off air" boolean field indicating that
the decode was derived from a .WAV file playback rather than an on air
reception.
- Extend reference applications to use the new off air decode message
field.
- Improve performance of FT8 decoder, especially for overlapping
signals.
- Allow specialized use of "x2 Tone Spacing" in FT8 and slow JT9
modes.
- Move "NA VHF Contest Mode" checkbox to main screen. Query the
operator if d > 10000 km.
- Adjust UI to improve portability with font size changes and between
platforms.
- Extend UDP Reply message to support keyboard modifiers. This allows
UDP servers to emulate keyboard modified double-clicks on decoded
messages, e.g. ALT+double-click for replying to a CQ or QRZ call
without changing ones Tx frequency offset.
- Update the cty.dat file (21st Sept 2017).
- Ensure that Fast Graph is properly initialized.
- Better handling of worked before and country name display. Appended
text is added at a fixed column unless the message overlaps in which
case the appended information floats to the right.
- Restore printing of MSK144 decode quality information.
- Display Echo Graph automatically when Echo mode is started.
- Fix a bug that prevented double-click on a JT65 EME-style "OOO"
message from populating the Tx message boxes.
- Fixed behavior with double-click on 'CQ <AA-ZZ> <call> <grid>.'
- Update the "blank line" divider with band ID at 4*TRperiod/5.
- Fix cty.dat lookups that were not honouring exact match flags
- Add some further Copyright protections.
- Fix a bug involving "firstcall contains mycall" but not equal to mycall.
- Fix an issue with editing IARU regions in the working frequencies table.
Release: WSJT-X Version 1.8.0-rc2
September 2, 2017
---------------------------------
Implementation of FT8 and its auto-sequencing feature is now more
capable and more polished. The decoder is faster and better: it now
includes signal subtraction, multi-pass decoding, and the use of
accumulated "a priori" information as a QSO progresses. Sensitivity
extends downward as far as -24 dB in some circumstances. Overlapping
signals 2 and 3 deep are frequently decoded at essentially the same
frequency. On a crowded band we sometimes see more than 30 decodes in
a single 15-second interval, over a 2 kHz window. The North American
VHF Contesting Mode has been extended to include both FT8 and MSK144
modes.
The "RC2" release also includes many minor bug fixes and an
extensively updated WSJT-X User Guide.
Depending on what code revision you upgrade from, it may be necessary
to do a one-time reset of the default list of suggested operating
frequencies. Go to *File->Settings->Frequencies*, right click on
the table and select *Reset*.
Release: WSJT-X Version 1.8.0
-----------------------------
NEW FEATURES IN WSJT-X Version 1.8.0
------------------------------------
1. New mode called FT8: sensitivity down to -20 dB on the AWGN
channel; QSOs 4 times faster than JT65 or JT9; auto-sequencing
includes an option to respond automatically to first decoded
reply to your CQ.
2. New mode for accurate Frequency Calibration of your radio.
3. Improved performance of decoders for JT65, QRA64, and MSK144.
MSK144 includes facilities for amplitide and phase equalization
and an "SWL" mode for short-format messages.
4. Options to minimize screen space used by Main and Wide Graph
windows.
5. Enhanced management scheme for table of operating frequencies, and
a new set of default frequencies specific to the three IARU
Regions.
6. Improved CAT control for many rigs, including those controlled
through Commander or OmniRig.
7. New keyboard shortcuts to set "Tx even/1st" ON or OFF.
8. A number of (mostly minor) bug fixes and tweaks to the user
interface. For example: new behavior for the audio level slider;
correctly logged QSO start times in certain situations; correct
control of FT-891/991 and some other radios via rigctld.
At the time of the v1.8.0-rc1 release the following tasks are yet to
be completed:
1. Updates to WSJT-X User Guide.
2. Sample files for FT8.
3. Enhanced decoding using AP ("a priori") information.
4. Signal subtraction and multi-pass decoding.
5. Option to Auto-respond to the weakest responder to your CQ.
Installation packages for Windows, Linux, OS X, and Raspbian can be
downloaded from the WSJT web site:
http://physics.princeton.edu/pulsar/K1JT/wsjtx.html
Please send bug reports to either wsjtgroup@yahoogroups.com or
wsjt-devel@lists.sourceforge.net. Such reports should include a full
prescription of steps to reproduce the undesired behavior. You must
be a subscriber to post to either of these lists.
Brief Description of the FT8 Protocol
-------------------------------------
WSJT-X Version 1.8.0 includes a new mode called FT8, developed by K9AN
and K1JT. The mode name "FT8" stands for "Franke and Taylor, 8-FSK
modulation". FT8 uses 15-second T/R sequences and provides 50% or
better decoding probability down to -20 dB on an AWGN channel. An
auto-sequencing facility includes an option to respond automatically
to the first decoded reply to your CQ. FT8 QSOs are 4 times faster
than those made with JT65 or JT9. FT8 is an excellent mode for HF
DXing and for situations like multi-hop E_s on 6 meters, where deep
QSB may make fast and reliable completion of QSOs desirable.
Some important characteristics of FT8:
- T/R sequence length: 15 s
- Message length: 75 bits + 12-bit CRC
- FEC code: LDPC(174,87)
- Modulation: 8-FSK, tone spacing 6.25 Hz
- Constant-envelope waveform
- Occupied bandwidth: 50 Hz
- Synchronization: 7x7 Costas arrays at start, middle, and end
- Transmission duration: 79*1920/12000 = 12.64 s
- Decoding threshold: -20 dB; several dB lower with AP decoding
- Multi-decoder finds and decodes all FT8 signals in passband
- Optional auto-sequencing and auto-reply to a CQ response
- Operational behavior similar to JT9, JT65
We plan to implement signal subtraction, two-pass decoding, and use of
a priori (AP) information in the decoder. These features are not yet
activated in v1.8.0.
We haven't yet finalized what the three extra bits in the message
payload will be used for. Suggestions are welcome!
-- Joe, K1JT, for the WSJT Development Team

View File

@ -33,6 +33,8 @@ void RemoteFile::local_file_path (QString const& name)
{ {
QFile file {local_file_.absoluteFilePath ()}; QFile file {local_file_.absoluteFilePath ()};
if (!file.rename (new_file.absoluteFilePath ())) if (!file.rename (new_file.absoluteFilePath ()))
{
if (listener_)
{ {
listener_->error (tr ("File System Error") listener_->error (tr ("File System Error")
, tr ("Cannot rename file:\n\"%1\"\nto: \"%2\"\nError(%3): %4") , tr ("Cannot rename file:\n\"%1\"\nto: \"%2\"\nError(%3): %4")
@ -42,6 +44,7 @@ void RemoteFile::local_file_path (QString const& name)
.arg (file.errorString ())); .arg (file.errorString ()));
} }
} }
}
std::swap (local_file_, new_file); std::swap (local_file_, new_file);
} }
} }
@ -49,6 +52,8 @@ void RemoteFile::local_file_path (QString const& name)
bool RemoteFile::local () const bool RemoteFile::local () const
{ {
auto is_local = (reply_ && !reply_->isFinished ()) || local_file_.exists (); auto is_local = (reply_ && !reply_->isFinished ()) || local_file_.exists ();
if (listener_)
{
if (is_local) if (is_local)
{ {
auto size = local_file_.size (); auto size = local_file_.size ();
@ -59,6 +64,7 @@ bool RemoteFile::local () const
{ {
listener_->download_progress (-1, 0); listener_->download_progress (-1, 0);
} }
}
return is_local; return is_local;
} }
@ -91,14 +97,20 @@ bool RemoteFile::sync (QUrl const& url, bool local, bool force)
{ {
auto path = local_file_.absoluteDir (); auto path = local_file_.absoluteDir ();
if (path.remove (local_file_.fileName ())) if (path.remove (local_file_.fileName ()))
{
if (listener_)
{ {
listener_->download_progress (-1, 0); listener_->download_progress (-1, 0);
} }
}
else else
{
if (listener_)
{ {
listener_->error (tr ("File System Error") listener_->error (tr ("File System Error")
, tr ("Cannot delete file:\n\"%1\"") , tr ("Cannot delete file:\n\"%1\"")
.arg (local_file_.absoluteFilePath ())); .arg (local_file_.absoluteFilePath ()));
}
return false; return false;
} }
path.rmpath ("."); path.rmpath (".");
@ -137,11 +149,14 @@ void RemoteFile::download (QUrl url)
connect (reply_.data (), &QNetworkReply::readyRead, this, &RemoteFile::store); connect (reply_.data (), &QNetworkReply::readyRead, this, &RemoteFile::store);
connect (reply_.data (), &QNetworkReply::downloadProgress connect (reply_.data (), &QNetworkReply::downloadProgress
, [this] (qint64 bytes_received, qint64 total_bytes) { , [this] (qint64 bytes_received, qint64 total_bytes) {
if (listener_)
{
// report progress of wanted file // report progress of wanted file
if (is_valid_) if (is_valid_)
{ {
listener_->download_progress (bytes_received, total_bytes); listener_->download_progress (bytes_received, total_bytes);
} }
}
}); });
} }
@ -160,7 +175,7 @@ void RemoteFile::reply_finished ()
QUrl redirect_url {reply_->attribute (QNetworkRequest::RedirectionTargetAttribute).toUrl ()}; QUrl redirect_url {reply_->attribute (QNetworkRequest::RedirectionTargetAttribute).toUrl ()};
if (reply_->error () == QNetworkReply::NoError && !redirect_url.isEmpty ()) if (reply_->error () == QNetworkReply::NoError && !redirect_url.isEmpty ())
{ {
if (listener_->redirect_request (redirect_url)) if (!listener_ || listener_->redirect_request (redirect_url))
{ {
if (++redirect_count_ < 10) // maintain sanity if (++redirect_count_ < 10) // maintain sanity
{ {
@ -168,20 +183,26 @@ void RemoteFile::reply_finished ()
download (reply_->url ().resolved (redirect_url)); download (reply_->url ().resolved (redirect_url));
} }
else else
{
if (listener_)
{ {
listener_->download_finished (false); listener_->download_finished (false);
listener_->error (tr ("Network Error") listener_->error (tr ("Network Error")
, tr ("Too many redirects: %1") , tr ("Too many redirects: %1")
.arg (redirect_url.toDisplayString ())); .arg (redirect_url.toDisplayString ()));
}
is_valid_ = false; // reset is_valid_ = false; // reset
} }
} }
else else
{
if (listener_)
{ {
listener_->download_finished (false); listener_->download_finished (false);
listener_->error (tr ("Network Error") listener_->error (tr ("Network Error")
, tr ("Redirect not followed: %1") , tr ("Redirect not followed: %1")
.arg (redirect_url.toDisplayString ())); .arg (redirect_url.toDisplayString ()));
}
is_valid_ = false; // reset is_valid_ = false; // reset
} }
} }
@ -189,10 +210,13 @@ void RemoteFile::reply_finished ()
{ {
file_.cancelWriting (); file_.cancelWriting ();
file_.commit (); file_.commit ();
if (listener_)
{
listener_->download_finished (false); listener_->download_finished (false);
}
is_valid_ = false; // reset is_valid_ = false; // reset
// report errors that are not due to abort // report errors that are not due to abort
if (QNetworkReply::OperationCanceledError != reply_->error ()) if (listener_ && QNetworkReply::OperationCanceledError != reply_->error ())
{ {
listener_->error (tr ("Network Error"), reply_->errorString ()); listener_->error (tr ("Network Error"), reply_->errorString ());
} }
@ -201,12 +225,18 @@ void RemoteFile::reply_finished ()
{ {
auto path = QFileInfo {file_.fileName ()}.absoluteDir (); auto path = QFileInfo {file_.fileName ()}.absoluteDir ();
if (is_valid_ && !file_.commit ()) if (is_valid_ && !file_.commit ())
{
if (listener_)
{ {
listener_->error (tr ("File System Error") listener_->error (tr ("File System Error")
, tr ("Cannot commit changes to:\n\"%1\"") , tr ("Cannot commit changes to:\n\"%1\"")
.arg (file_.fileName ())); .arg (file_.fileName ()));
}
path.rmpath ("."); // tidy empty directories path.rmpath ("."); // tidy empty directories
if (listener_)
{
listener_->download_finished (false); listener_->download_finished (false);
}
is_valid_ = false; // reset is_valid_ = false; // reset
} }
else else
@ -218,8 +248,11 @@ void RemoteFile::reply_finished ()
download (reply_->url ().resolved (redirect_url)); download (reply_->url ().resolved (redirect_url));
} }
else else
{
if (listener_)
{ {
listener_->download_finished (true); listener_->download_finished (true);
}
is_valid_ = false; // reset is_valid_ = false; // reset
} }
} }
@ -243,6 +276,8 @@ void RemoteFile::store ()
if (!file_.open (QSaveFile::WriteOnly)) if (!file_.open (QSaveFile::WriteOnly))
{ {
abort (); abort ();
if (listener_)
{
listener_->error (tr ("File System Error") listener_->error (tr ("File System Error")
, tr ("Cannot open file:\n\"%1\"\nError(%2): %3") , tr ("Cannot open file:\n\"%1\"\nError(%2): %3")
.arg (path.path ()) .arg (path.path ())
@ -250,17 +285,23 @@ void RemoteFile::store ()
.arg (file_.errorString ())); .arg (file_.errorString ()));
} }
} }
}
else else
{ {
abort (); abort ();
if (listener_)
{
listener_->error (tr ("File System Error") listener_->error (tr ("File System Error")
, tr ("Cannot make path:\n\"%1\"") , tr ("Cannot make path:\n\"%1\"")
.arg (path.path ())); .arg (path.path ()));
} }
} }
}
if (file_.write (reply_->read (reply_->bytesAvailable ())) < 0) if (file_.write (reply_->read (reply_->bytesAvailable ())) < 0)
{ {
abort (); abort ();
if (listener_)
{
listener_->error (tr ("File System Error") listener_->error (tr ("File System Error")
, tr ("Cannot write to file:\n\"%1\"\nError(%2): %3") , tr ("Cannot write to file:\n\"%1\"\nError(%2): %3")
.arg (file_.fileName ()) .arg (file_.fileName ())
@ -268,4 +309,5 @@ void RemoteFile::store ()
.arg (file_.errorString ())); .arg (file_.errorString ()));
} }
} }
}
} }

View File

@ -6,18 +6,9 @@
#include <QString> #include <QString>
#include <QFile> #include <QFile>
#include <QTextStream> #include <QTextStream>
#include <QMessageLogContext>
#include <QDateTime>
#include <QMutex>
#include <QMutexLocker>
#include "pimpl_impl.hpp" #include "pimpl_impl.hpp"
namespace
{
QMutex lock;
}
class TraceFile::impl class TraceFile::impl
{ {
public: public:
@ -81,35 +72,8 @@ TraceFile::impl::~impl ()
// write Qt messages to the diagnostic log file // write Qt messages to the diagnostic log file
void TraceFile::impl::message_handler (QtMsgType type, QMessageLogContext const& context, QString const& msg) void TraceFile::impl::message_handler (QtMsgType type, QMessageLogContext const& context, QString const& msg)
{ {
char const * severity;
switch (type)
{
case QtDebugMsg:
severity = "Debug";
break;
case QtWarningMsg:
severity = "Warning";
break;
case QtFatalMsg:
severity = "Fatal";
break;
default:
severity = "Critical";
break;
}
{
// guard against multiple threads with overlapping messages
QMutexLocker guard (&lock);
Q_ASSERT_X (current_stream_, "TraceFile:message_handler", "no stream to write to"); Q_ASSERT_X (current_stream_, "TraceFile:message_handler", "no stream to write to");
*current_stream_ *current_stream_ << qFormatLogMessage (type, context, msg) << endl;
<< QDateTime::currentDateTimeUtc ().toString ("yyyy-MM-ddTHH:mm:ss.zzzZ")
<< '(' << context.file << ':' << context.line /* << ", " << context.function */ << ')'
<< severity << ": " << msg.trimmed () << endl;
}
if (QtFatalMsg == type) if (QtFatalMsg == type)
{ {

View File

@ -3,9 +3,6 @@
#include "moc_Transceiver.cpp" #include "moc_Transceiver.cpp"
#if !defined (QT_NO_DEBUG_STREAM) #if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_IMPL (Transceiver, MODE);
QDebug operator << (QDebug d, Transceiver::TransceiverState const& s) QDebug operator << (QDebug d, Transceiver::TransceiverState const& s)
{ {
d.nospace () d.nospace ()
@ -16,7 +13,6 @@ QDebug operator << (QDebug d, Transceiver::TransceiverState const& s)
<< ')'; << ')';
return d.space (); return d.space ();
} }
#endif #endif
ENUM_QDATASTREAM_OPS_IMPL (Transceiver, MODE); ENUM_QDATASTREAM_OPS_IMPL (Transceiver, MODE);

View File

@ -52,7 +52,6 @@ class Transceiver
: public QObject : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_ENUMS (MODE)
public: public:
using Frequency = Radio::Frequency; using Frequency = Radio::Frequency;
@ -154,13 +153,8 @@ public:
}; };
Q_DECLARE_METATYPE (Transceiver::TransceiverState); Q_DECLARE_METATYPE (Transceiver::TransceiverState);
#if QT_VERSION < 0x050500
Q_DECLARE_METATYPE (Transceiver::MODE);
#endif
#if !defined (QT_NO_DEBUG_STREAM) #if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_DECL (Transceiver, MODE);
QDebug operator << (QDebug, Transceiver::TransceiverState const&); QDebug operator << (QDebug, Transceiver::TransceiverState const&);
#endif #endif

View File

@ -197,15 +197,6 @@ std::unique_ptr<Transceiver> TransceiverFactory::create (ParameterPack const& pa
return result; return result;
} }
#if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, DataBits);
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, StopBits);
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, Handshake);
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, PTTMethod);
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, TXAudioSource);
ENUM_QDEBUG_OPS_IMPL (TransceiverFactory, SplitMode);
#endif
ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, DataBits); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, DataBits);
ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, StopBits); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, StopBits);
ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, Handshake); ENUM_QDATASTREAM_OPS_IMPL (TransceiverFactory, Handshake);

View File

@ -21,7 +21,6 @@ class TransceiverFactory
: public QObject : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_ENUMS (DataBits StopBits Handshake PTTMethod TXAudioSource SplitMode)
public: public:
// //
@ -161,28 +160,6 @@ bool operator != (TransceiverFactory::ParameterPack const& lhs, TransceiverFacto
return !(lhs == rhs); return !(lhs == rhs);
} }
//
// boilerplate routines to make enum types useable and debuggable in
// Qt
//
#if QT_VERSION < 0x050500
Q_DECLARE_METATYPE (TransceiverFactory::DataBits);
Q_DECLARE_METATYPE (TransceiverFactory::StopBits);
Q_DECLARE_METATYPE (TransceiverFactory::Handshake);
Q_DECLARE_METATYPE (TransceiverFactory::PTTMethod);
Q_DECLARE_METATYPE (TransceiverFactory::TXAudioSource);
Q_DECLARE_METATYPE (TransceiverFactory::SplitMode);
#endif
#if !defined (QT_NO_DEBUG_STREAM)
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, DataBits);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, StopBits);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, Handshake);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, PTTMethod);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, TXAudioSource);
ENUM_QDEBUG_OPS_DECL (TransceiverFactory, SplitMode);
#endif
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, DataBits); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, DataBits);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, StopBits); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, StopBits);
ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, Handshake); ENUM_QDATASTREAM_OPS_DECL (TransceiverFactory, Handshake);

View File

@ -1,3 +1,4 @@
# Version number components # Version number components
set (WSJTX_VERSION_MAJOR 2) set (WSJTX_VERSION_MAJOR 2)
set (WSJTX_VERSION_MINOR 0) set (WSJTX_VERSION_MINOR 0)

View File

@ -1,23 +1,28 @@
#include "colorhighlighting.h" #include "colorhighlighting.h"
#include "ui_colorhighlighting.h"
#include "SettingsGroup.hpp"
#include <QApplication> #include <QApplication>
#include <QDebug> #include <QDebug>
ColorHighlighting::ColorHighlighting(QSettings *settings, QWidget *parent) : #include "SettingsGroup.hpp"
QDialog(parent), #include "DecodeHighlightingModel.hpp"
settings_ {settings},
ui(new Ui::ColorHighlighting) #include "ui_colorhighlighting.h"
#include "moc_colorhighlighting.cpp"
ColorHighlighting::ColorHighlighting (QSettings * settings, DecodeHighlightingModel const& highlight_model, QWidget * parent)
: QDialog {parent}
, ui {new Ui::ColorHighlighting}
, settings_ {settings}
{ {
ui->setupUi(this); ui->setupUi(this);
setWindowTitle (QApplication::applicationName () + " - Colors");
read_settings (); read_settings ();
set_items (highlight_model);
} }
ColorHighlighting::~ColorHighlighting() ColorHighlighting::~ColorHighlighting()
{ {
if (isVisible ()) write_settings (); if (isVisible ()) write_settings ();
delete ui;
} }
void ColorHighlighting::read_settings () void ColorHighlighting::read_settings ()
@ -32,21 +37,68 @@ void ColorHighlighting::write_settings ()
settings_->setValue ("window/geometry", saveGeometry ()); settings_->setValue ("window/geometry", saveGeometry ());
} }
void ColorHighlighting::set_items (DecodeHighlightingModel const& highlighting_model)
void ColorHighlighting::colorHighlightlingSetup(QColor color_CQ,QColor color_MyCall,
QColor color_DXCC,QColor color_DXCCband,QColor color_NewCall,
QColor color_NewCallBand,QColor color_NewGrid,QColor color_NewGridBand,
QColor color_TxMsg,QColor color_LoTW)
{ {
setWindowTitle(QApplication::applicationName() + " - Colors"); int index {0};
ui->label->setStyleSheet(QString("background: %1").arg(color_CQ.name())); for (auto const& item : highlighting_model.items ())
ui->label_3->setStyleSheet(QString("background: %1").arg(color_MyCall.name())); {
ui->label_5->setStyleSheet(QString("background: %1").arg(color_TxMsg.name())); QLabel * example;
ui->label_7->setStyleSheet(QString("background: %1").arg(color_DXCC.name())); QLabel * label;
ui->label_9->setStyleSheet(QString("background: %1").arg(color_DXCCband.name())); switch (index++)
ui->label_11->setStyleSheet(QString("background: %1").arg(color_NewCall.name())); {
ui->label_13->setStyleSheet(QString("background: %1").arg(color_NewCallBand.name())); case 0:
ui->label_15->setStyleSheet(QString("background: %1").arg(color_NewGrid.name())); example = ui->example1_label;
ui->label_17->setStyleSheet(QString("background: %1").arg(color_NewGridBand.name())); label = ui->p1_label;
ui->label_19->setStyleSheet(QString("color: %1").arg(color_LoTW.name())); break;
case 1:
example = ui->example2_label;
label = ui->p2_label;
break;
case 2:
example = ui->example3_label;
label = ui->p3_label;
break;
case 3:
example = ui->example4_label;
label = ui->p4_label;
break;
case 4:
example = ui->example5_label;
label = ui->p5_label;
break;
case 5:
example = ui->example6_label;
label = ui->p6_label;
break;
case 6:
example = ui->example7_label;
label = ui->p7_label;
break;
case 7:
example = ui->example8_label;
label = ui->p8_label;
break;
case 8:
example = ui->example9_label;
label = ui->p9_label;
break;
case 9:
example = ui->example10_label;
label = ui->p10_label;
break;
}
auto palette = example->parentWidget ()->palette ();
if (Qt::NoBrush != item.background_.style ())
{
palette.setColor (QPalette::Window, item.background_.color ());
}
if (Qt::NoBrush != item.foreground_.style ())
{
palette.setColor (QPalette::WindowText, item.foreground_.color ());
}
example->setPalette (palette);
example->setEnabled (item.enabled_);
label->setText (DecodeHighlightingModel::highlight_name (item.type_));
label->setEnabled (item.enabled_);
}
} }

View File

@ -1,30 +1,33 @@
#ifndef COLORHIGHLIGHTING_H #ifndef COLORHIGHLIGHTING_H_
#define COLORHIGHLIGHTING_H #define COLORHIGHLIGHTING_H_
#include <QDialog> #include <QDialog>
#include <QSettings> #include <QScopedPointer>
class QSettings;
class DecodeHighlightingModel;
namespace Ui { namespace Ui {
class ColorHighlighting; class ColorHighlighting;
} }
class ColorHighlighting : public QDialog class ColorHighlighting final
: public QDialog
{ {
Q_OBJECT Q_OBJECT;
public: public:
explicit ColorHighlighting(QSettings *, QWidget *parent = 0); explicit ColorHighlighting(QSettings *, DecodeHighlightingModel const&, QWidget * parent = nullptr);
~ColorHighlighting(); ~ColorHighlighting ();
void colorHighlightlingSetup(QColor color_CQ, QColor color_MyCall,
QColor color_DXCC, QColor color_DXCCband, QColor color_NewCall,
QColor color_NewCallBand, QColor color_NewGrid, QColor color_NewGridBand,
QColor color_TxMsg, QColor color_LoTW);
private: Q_SLOT void set_items (DecodeHighlightingModel const&);
QSettings * settings_;
private:
void read_settings (); void read_settings ();
void write_settings (); void write_settings ();
Ui::ColorHighlighting *ui;
QScopedPointer<Ui::ColorHighlighting> ui;
QSettings * settings_;
}; };
#endif // COLORHIGHLIGHTING_H #endif

View File

@ -10,119 +10,12 @@
<height>253</height> <height>253</height>
</rect> </rect>
</property> </property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="6" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_15">
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Transmitted message</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="label_14">
<property name="text">
<string>New Call on Band</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="label_12">
<property name="text">
<string>New Call</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="label_16">
<property name="text">
<string>New Grid</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="label_18">
<property name="text">
<string>New Grid on Band</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="label"> <widget class="QLabel" name="example1_label">
<property name="text"> <property name="autoFillBackground">
<string>K1ABC</string> <bool>true</bool>
</property> </property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_9">
<property name="text"> <property name="text">
<string>K1ABC</string> <string>K1ABC</string>
</property> </property>
@ -132,21 +25,77 @@
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="0" column="1">
<widget class="QLabel" name="label_2"> <widget class="QLabel" name="p1_label">
<property name="text"> <property name="text">
<string>CQ in message</string> <string>CQ in message</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QLabel" name="example2_label">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QLabel" name="label_4"> <widget class="QLabel" name="p2_label">
<property name="text"> <property name="text">
<string>My Call in message</string> <string>My Call in message</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QLabel" name="example3_label">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="p3_label">
<property name="text">
<string>Transmitted message</string>
</property>
</widget>
</item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label_7"> <widget class="QLabel" name="example4_label">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="p4_label">
<property name="text">
<string>New DXCC</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="example5_label">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="text"> <property name="text">
<string>K1ABC</string> <string>K1ABC</string>
</property> </property>
@ -156,21 +105,97 @@
</widget> </widget>
</item> </item>
<item row="4" column="1"> <item row="4" column="1">
<widget class="QLabel" name="label_10"> <widget class="QLabel" name="p5_label">
<property name="text"> <property name="text">
<string>New DXCC on Band</string> <string>New DXCC on Band</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1"> <item row="5" column="0">
<widget class="QLabel" name="label_8"> <widget class="QLabel" name="example6_label">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="text"> <property name="text">
<string>New DXCC</string> <string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="p6_label">
<property name="text">
<string>New Grid</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QLabel" name="example7_label">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="p7_label">
<property name="text">
<string>New Grid on Band</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="example8_label">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="p8_label">
<property name="text">
<string>New Call</string>
</property>
</widget>
</item>
<item row="8" column="0">
<widget class="QLabel" name="example9_label">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="text">
<string>K1ABC</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QLabel" name="p9_label">
<property name="text">
<string>New Call on Band</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="9" column="0"> <item row="9" column="0">
<widget class="QLabel" name="label_19"> <widget class="QLabel" name="example10_label">
<property name="autoFillBackground">
<bool>true</bool>
</property>
<property name="text"> <property name="text">
<string>K1ABC</string> <string>K1ABC</string>
</property> </property>
@ -180,15 +205,13 @@
</widget> </widget>
</item> </item>
<item row="9" column="1"> <item row="9" column="1">
<widget class="QLabel" name="label_20"> <widget class="QLabel" name="p10_label">
<property name="text"> <property name="text">
<string>Not in LoTW</string> <string>Uploads to LotW</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> </layout>
</item>
</layout>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>

File diff suppressed because it is too large Load Diff

1849
cty.dat

File diff suppressed because it is too large Load Diff

View File

@ -12,11 +12,11 @@ JT65 111010000000111000010000000000001
JT65/VHF 111110010000111110101100010000000 JT65/VHF 111110010000111110101100010000000
QRA64 111110010110111110000000001000000 QRA64 111110010110111110000000001000000
ISCAT 100111000000000110000000000000000 ISCAT 100111000000000110000000000000000
MSK144 101111110100000000010001000010000 MSK144 101111110100000000010001000000000
WSPR 000000000000000001010000000000000 WSPR 000000000000000001010000000000000
Echo 000000000000000000000010000000000 Echo 000000000000000000000010000000000
FCal 001101000000000000000000000001000 FCal 001101000000000000000000000001000
FT8 111010000100111000010000100100001 FT8 111010000100111000010000100110001
FT8/VHF 111010000100111000010000100110001 FT8/VHF 111010000100111000010000100110001
FT8/Fox 111010000100111000010000000000100 FT8/Fox 111010000100111000010000000000100
FT8/Hound 111010000100111000010000000000110 FT8/Hound 111010000100111000010000000000110
@ -55,7 +55,7 @@ Mapping of column numbers to widgets
25. AP JT65 25. AP JT65
26. AP DX Call 26. AP DX Call
27. cbFirst 27. cbFirst
28. cbVHFcontest 28. labNextCall
29. measure_check_box 29. measure_check_box
30. labDXped 30. labDXped
31. cbRxAll 31. cbRxAll

View File

@ -1,5 +1,4 @@
#include "displaytext.h" #include "displaytext.h"
#include "mainwindow.h"
#include <QMouseEvent> #include <QMouseEvent>
#include <QDateTime> #include <QDateTime>
#include <QTextCharFormat> #include <QTextCharFormat>
@ -8,12 +7,16 @@
#include <QMenu> #include <QMenu>
#include <QAction> #include <QAction>
#include "qt_helpers.hpp" #include "Configuration.hpp"
#include "LotWUsers.hpp"
#include "DecodeHighlightingModel.hpp"
#include "qt_helpers.hpp"
#include "moc_displaytext.cpp" #include "moc_displaytext.cpp"
DisplayText::DisplayText(QWidget *parent) DisplayText::DisplayText(QWidget *parent)
: QTextEdit(parent) : QTextEdit(parent)
, m_config {nullptr}
, erase_action_ {new QAction {tr ("&Erase"), this}} , erase_action_ {new QAction {tr ("&Erase"), this}}
{ {
setReadOnly (true); setReadOnly (true);
@ -73,14 +76,54 @@ void DisplayText::insertLineSpacer(QString const& line)
appendText (line, "#d3d3d3"); appendText (line, "#d3d3d3");
} }
void DisplayText::appendText(QString const& text, QColor bg, namespace
QString const& call1, QString const& call2) {
void set_colours (Configuration const * config, QColor * bg, QColor * fg, DecodeHighlightingModel::Highlight type)
{
if (config)
{
for (auto const& item : config->decode_highlighting ().items ())
{
if (type == item.type_ && item.enabled_)
{
if (item.background_.style () != Qt::NoBrush)
{
*bg = item.background_.color ();
}
if (item.foreground_.style () != Qt::NoBrush)
{
*fg = item.foreground_.color ();
}
break;
}
}
}
}
}
void DisplayText::appendText(QString const& text, QColor bg, QColor fg
, QString const& call1, QString const& call2)
{ {
// qDebug () << "DisplayText::appendText: text:" << text << "Nbsp pos:" << text.indexOf (QChar::Nbsp); // qDebug () << "DisplayText::appendText: text:" << text << "Nbsp pos:" << text.indexOf (QChar::Nbsp);
auto cursor = textCursor (); auto cursor = textCursor ();
cursor.movePosition (QTextCursor::End); cursor.movePosition (QTextCursor::End);
auto block_format = cursor.blockFormat (); auto block_format = cursor.blockFormat ();
if (bg.isValid ())
{
block_format.setBackground (bg); block_format.setBackground (bg);
}
else
{
block_format.clearBackground ();
}
if (fg.isValid ())
{
block_format.setForeground (fg);
}
else
{
block_format.clearForeground ();
}
if (0 == cursor.position ()) if (0 == cursor.position ())
{ {
cursor.setBlockFormat (block_format); cursor.setBlockFormat (block_format);
@ -91,10 +134,13 @@ void DisplayText::appendText(QString const& text, QColor bg,
else else
{ {
cursor.insertBlock (block_format); cursor.insertBlock (block_format);
auto char_format = cursor.charFormat ();
char_format.clearBackground ();
char_format.clearForeground ();
cursor.setCharFormat (char_format);
} }
QTextCharFormat format = cursor.charFormat(); QTextCharFormat format = cursor.charFormat();
format.clearBackground();
int text_index {0}; int text_index {0};
if (call1.size ()) if (call1.size ())
{ {
@ -127,7 +173,7 @@ void DisplayText::appendText(QString const& text, QColor bg,
if (pos != highlighted_calls_.end ()) if (pos != highlighted_calls_.end ())
{ {
format.setBackground (bg); format.setBackground (bg);
format.clearForeground (); format.setForeground (fg);
cursor.insertText(text.mid (text_index, call_index - text_index), format); cursor.insertText(text.mid (text_index, call_index - text_index), format);
if (pos.value ().second.isValid ()) if (pos.value ().second.isValid ())
{ {
@ -142,10 +188,13 @@ void DisplayText::appendText(QString const& text, QColor bg,
} }
} }
} }
format.setBackground (bg); if (call2.size () && m_config && m_config->lotw_users ().user (call2))
format.clearForeground (); {
if(call2.size()>0 and !m_LoTW.contains(call2)) { QColor bg;
format.setForeground(m_color_LoTW); //Mark LoTW non-users QColor fg;
set_colours (m_config, &bg, &fg, DecodeHighlightingModel::Highlight::LotW);
if (bg.isValid ()) format.setBackground (bg);
if (fg.isValid ()) format.setForeground (fg);
} }
cursor.insertText(text.mid (text_index), format); cursor.insertText(text.mid (text_index), format);
@ -157,7 +206,7 @@ void DisplayText::appendText(QString const& text, QColor bg,
} }
QString DisplayText::appendWorkedB4(QString message, QString const& callsign, QString grid, QString DisplayText::appendWorkedB4(QString message, QString const& callsign, QString grid,
QColor * bg, LogBook const& logBook, QString currentBand) QColor * bg, QColor * fg, LogBook const& logBook, QString currentBand)
{ {
// allow for seconds // allow for seconds
int padding {message.indexOf (" ") > 4 ? 2 : 0}; int padding {message.indexOf (" ") > 4 ? 2 : 0};
@ -192,29 +241,29 @@ QString DisplayText::appendWorkedB4(QString message, QString const& callsign, QS
if (!countryWorkedBefore) { if (!countryWorkedBefore) {
// therefore not worked call either // therefore not worked call either
// appendage += "!"; // appendage += "!";
*bg = m_color_DXCC; set_colours (m_config, bg, fg, DecodeHighlightingModel::Highlight::CQ);
} else { } else {
if(!countryB4onBand) { if(!countryB4onBand) {
*bg = m_color_DXCCband; set_colours (m_config, bg, fg, DecodeHighlightingModel::Highlight::DXCCBand);
} else { } else {
if(!gridB4) { if(!gridB4) {
*bg = m_color_NewGrid; set_colours (m_config, bg, fg, DecodeHighlightingModel::Highlight::Grid);
} else { } else {
if(!gridB4onBand) { if(!gridB4onBand) {
*bg = m_color_NewGridBand; set_colours (m_config, bg, fg, DecodeHighlightingModel::Highlight::GridBand);
} else { } else {
if (!callWorkedBefore) { if (!callWorkedBefore) {
// but have worked the country // but have worked the country
// appendage += "~"; // appendage += "~";
*bg = m_color_NewCall; set_colours (m_config, bg, fg, DecodeHighlightingModel::Highlight::Call);
} else { } else {
if(!callB4onBand) { if(!callB4onBand) {
// appendage += "~"; // appendage += "~";
*bg = m_color_NewCallBand; set_colours (m_config, bg, fg, DecodeHighlightingModel::Highlight::CallBand);
} else { } else {
// appendage += " "; // have worked this call before // appendage += " "; // have worked this call before
*bg = m_color_CQ; set_colours (m_config, bg, fg, DecodeHighlightingModel::Highlight::CQ);
} }
} }
} }
@ -267,14 +316,15 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
QString currentBand, bool ppfx, bool bCQonly) QString currentBand, bool ppfx, bool bCQonly)
{ {
m_bPrincipalPrefix=ppfx; m_bPrincipalPrefix=ppfx;
QColor bg {Qt::transparent}; QColor bg;
QColor fg;
bool CQcall = false; bool CQcall = false;
if (decodedText.string ().contains (" CQ ") if (decodedText.string ().contains (" CQ ")
|| decodedText.string ().contains (" CQDX ") || decodedText.string ().contains (" CQDX ")
|| decodedText.string ().contains (" QRZ ")) || decodedText.string ().contains (" QRZ "))
{ {
CQcall = true; CQcall = true;
bg = m_color_CQ; set_colours (m_config, &bg, &fg, DecodeHighlightingModel::Highlight::CQ);
} }
if(bCQonly and !CQcall) return; if(bCQonly and !CQcall) return;
if (myCall != "" and (decodedText.indexOf (" " + myCall + " ") >= 0 if (myCall != "" and (decodedText.indexOf (" " + myCall + " ") >= 0
@ -285,7 +335,7 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
or decodedText.indexOf ("<" + myCall + " ") >= 0 or decodedText.indexOf ("<" + myCall + " ") >= 0
or decodedText.indexOf ("<" + myCall + ">") >= 0 or decodedText.indexOf ("<" + myCall + ">") >= 0
or decodedText.indexOf (" " + myCall + ">") >= 0)) { or decodedText.indexOf (" " + myCall + ">") >= 0)) {
bg = m_color_MyCall; set_colours (m_config, &bg, &fg, DecodeHighlightingModel::Highlight::MyCall);
} }
auto message = decodedText.string(); auto message = decodedText.string();
QString dxCall; QString dxCall;
@ -297,8 +347,8 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
if (displayDXCCEntity && CQcall) if (displayDXCCEntity && CQcall)
// if enabled add the DXCC entity and B4 status to the end of the // if enabled add the DXCC entity and B4 status to the end of the
// preformated text line t1 // preformated text line t1
message = appendWorkedB4 (message, decodedText.CQersCall(), dxGrid, &bg, logBook, currentBand); message = appendWorkedB4 (message, decodedText.CQersCall(), dxGrid, &bg, &fg, logBook, currentBand);
appendText (message.trimmed (), bg, decodedText.call (), dxCall); appendText (message.trimmed (), bg, fg, decodedText.call (), dxCall);
} }
@ -322,7 +372,10 @@ void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 tx
t = QDateTime::currentDateTimeUtc().toString("hhmm") + \ t = QDateTime::currentDateTimeUtc().toString("hhmm") + \
" Tx " + t2 + t1 + text; " Tx " + t2 + t1 + text;
} }
appendText (t, m_color_TxMsg); QColor bg;
QColor fg;
set_colours (m_config, &bg, &fg, DecodeHighlightingModel::Highlight::Tx);
appendText (t, bg, fg);
} }
void DisplayText::displayQSY(QString text) void DisplayText::displayQSY(QString text)
@ -331,9 +384,9 @@ void DisplayText::displayQSY(QString text)
appendText (t, "hotpink"); appendText (t, "hotpink");
} }
void DisplayText::displayFoxToBeCalled(QString t, QColor bg) void DisplayText::displayFoxToBeCalled(QString t, QColor bg, QColor fg)
{ {
appendText(t,bg); appendText (t, bg, fg);
} }
namespace namespace
@ -429,20 +482,3 @@ void DisplayText::highlight_callsign (QString const& callsign, QColor const& bg,
} }
setCurrentCharFormat (old_format); setCurrentCharFormat (old_format);
} }
void DisplayText::setDecodedTextColors(QColor color_CQ, QColor color_MyCall,
QColor color_DXCC, QColor color_DXCCband,QColor color_NewCall,QColor color_NewCallBand,
QColor color_NewGrid, QColor color_NewGridBand,QColor color_TxMsg,QColor color_LoTW)
{
// Save the color highlighting scheme selected by the user.
m_color_CQ=color_CQ;
m_color_DXCC=color_DXCC;
m_color_DXCCband=color_DXCCband;
m_color_MyCall=color_MyCall;
m_color_NewCall=color_NewCall;
m_color_NewCallBand=color_NewCallBand;
m_color_NewGrid=color_NewGrid;
m_color_NewGridBand=color_NewGridBand;
m_color_TxMsg=color_TxMsg;
m_color_LoTW=color_LoTW;
}

View File

@ -12,6 +12,7 @@
#include "decodedtext.h" #include "decodedtext.h"
class QAction; class QAction;
class Configuration;
class DisplayText class DisplayText
: public QTextEdit : public QTextEdit
@ -19,7 +20,7 @@ class DisplayText
Q_OBJECT Q_OBJECT
public: public:
explicit DisplayText(QWidget *parent = 0); explicit DisplayText(QWidget *parent = 0);
void set_configuration (Configuration const * configuration) {m_config = configuration;}
void setContentFont (QFont const&); void setContentFont (QFont const&);
void insertLineSpacer(QString const&); void insertLineSpacer(QString const&);
void displayDecodedText(DecodedText const& decodedText, QString const& myCall, void displayDecodedText(DecodedText const& decodedText, QString const& myCall,
@ -27,16 +28,12 @@ public:
QString currentBand="", bool ppfx=false, bool bCQonly=false); QString currentBand="", bool ppfx=false, bool bCQonly=false);
void displayTransmittedText(QString text, QString modeTx, qint32 txFreq, bool bFastMode); void displayTransmittedText(QString text, QString modeTx, qint32 txFreq, bool bFastMode);
void displayQSY(QString text); void displayQSY(QString text);
void displayFoxToBeCalled(QString t, QColor bg); void displayFoxToBeCalled(QString t, QColor bg = QColor {}, QColor fg = QColor {});
void setDecodedTextColors(QColor color_CQ, QColor color_MyCall, QColor color_DXCC,
QColor color_DXCCband, QColor color_NewCall, QColor color_NewCallBand,
QColor color_NewGrid, QColor color_NewGridBand, QColor color_TxMsg,
QColor color_LoTW);
Q_SIGNAL void selectCallsign (Qt::KeyboardModifiers); Q_SIGNAL void selectCallsign (Qt::KeyboardModifiers);
Q_SIGNAL void erased (); Q_SIGNAL void erased ();
Q_SLOT void appendText (QString const& text, QColor bg = Qt::white Q_SLOT void appendText (QString const& text, QColor bg = QColor {}, QColor fg = QColor {}
, QString const& call1 = QString {}, QString const& call2 = QString {}); , QString const& call1 = QString {}, QString const& call2 = QString {});
Q_SLOT void erase (); Q_SLOT void erase ();
Q_SLOT void highlight_callsign (QString const& callsign, QColor const& bg, QColor const& fg, bool last_only); Q_SLOT void highlight_callsign (QString const& callsign, QColor const& bg, QColor const& fg, bool last_only);
@ -45,22 +42,14 @@ protected:
void mouseDoubleClickEvent(QMouseEvent *e); void mouseDoubleClickEvent(QMouseEvent *e);
private: private:
Configuration const * m_config;
bool m_bPrincipalPrefix; bool m_bPrincipalPrefix;
QString appendWorkedB4(QString message, QString const& callsign, QString grid, QColor * bg, QString appendWorkedB4(QString message, QString const& callsign
LogBook const& logBook, QString currentBand); , QString grid, QColor * bg, QColor * fg
, LogBook const& logBook, QString currentBand);
QFont char_font_; QFont char_font_;
QAction * erase_action_; QAction * erase_action_;
QHash<QString, QPair<QColor, QColor>> highlighted_calls_; QHash<QString, QPair<QColor, QColor>> highlighted_calls_;
QColor m_color_CQ;
QColor m_color_MyCall;
QColor m_color_DXCC;
QColor m_color_DXCCband;
QColor m_color_NewCall;
QColor m_color_NewCallBand;
QColor m_color_NewGrid;
QColor m_color_NewGridBand;
QColor m_color_LoTW;
QColor m_color_TxMsg;
}; };
extern QHash<QString,int> m_LoTW; extern QHash<QString,int> m_LoTW;

View File

@ -1,6 +1,6 @@
gfortran -c ../packjt.f90 gfortran -c ../packjt.f90
gfortran -c packjt77.f90 gfortran -c packjt77.f90
gfortran -o encode77 -fbounds-check -Wall -Wno-conversion -Wno-real-q-constant \ gfortran -o encode77 -fbounds-check -Wall -Wno-conversion \
encode77.f90 ../deg2grid.f90 ../grid2deg.f90 ../fix_contest_msg.f90 \ encode77.f90 ../deg2grid.f90 ../grid2deg.f90 ../fix_contest_msg.f90 \
../to_contest_msg.f90 ../fmtmsg.f90 ../azdist.f90 ../geodist.f90 \ ../to_contest_msg.f90 ../fmtmsg.f90 ../azdist.f90 ../geodist.f90 \
packjt.o packjt77.o packjt.o packjt77.o

View File

@ -17,10 +17,7 @@ subroutine hash10(n10,c13)
do i=1,nzhash do i=1,nzhash
if(ihash10(i).eq.n10) then if(ihash10(i).eq.n10) then
c13=callsign(i) c13=callsign(i)
if(c13(1:1).ne.'<') then
n=len(trim(c13))
c13='<'//trim(c13)//'>'//' ' c13='<'//trim(c13)//'>'//' '
endif
go to 900 go to 900
endif endif
enddo enddo
@ -36,10 +33,7 @@ subroutine hash12(n12,c13)
do i=1,nzhash do i=1,nzhash
if(ihash12(i).eq.n12) then if(ihash12(i).eq.n12) then
c13=callsign(i) c13=callsign(i)
if(c13(1:1).ne.'<') then
n=len(trim(c13))
c13='<'//trim(c13)//'>'//' ' c13='<'//trim(c13)//'>'//' '
endif
go to 900 go to 900
endif endif
enddo enddo
@ -56,10 +50,7 @@ subroutine hash22(n22,c13)
do i=1,nzhash do i=1,nzhash
if(ihash22(i).eq.n22) then if(ihash22(i).eq.n22) then
c13=callsign(i) c13=callsign(i)
if(c13(1:1).ne.'<') then
n=len(trim(c13))
c13='<'//trim(c13)//'>'//' ' c13='<'//trim(c13)//'>'//' '
endif
go to 900 go to 900
endif endif
enddo enddo
@ -71,17 +62,13 @@ end subroutine hash22
integer function ihashcall(c0,m) integer function ihashcall(c0,m)
integer*8 n8 integer*8 n8
character*13 c0,c1 character*13 c0
character*38 c character*38 c
data c/' 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ/'/ data c/' 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ/'/
c1=c0
if(c1(1:1).eq.'<') c1=c1(2:)
i=index(c1,'>')
if(i.gt.0) c1(i:)=' '
n8=0 n8=0
do i=1,11 do i=1,11
j=index(c,c1(i:i)) - 1 j=index(c,c0(i:i)) - 1
n8=38*n8 + j n8=38*n8 + j
enddo enddo
ihashcall=ishft(47055833459_8*n8,m-64) ihashcall=ishft(47055833459_8*n8,m-64)
@ -91,7 +78,7 @@ end function ihashcall
subroutine save_hash_call(c13,n10,n12,n22) subroutine save_hash_call(c13,n10,n12,n22)
character*13 c13 character*13 c13,cw
logical first logical first
data first/.true./ data first/.true./
save first save first
@ -105,11 +92,15 @@ subroutine save_hash_call(c13,n10,n12,n22)
first=.false. first=.false.
endif endif
if(c13(1:1).eq.' ' .or. c13(1:5).eq.'<...>') return cw=c13
if(cw(1:1).eq.' ' .or. cw(1:5).eq.'<...>') return
if(cw(1:1).eq.'<') cw=cw(2:)
i=index(cw,'>')
if(i.gt.0) cw(i:)=' '
n10=ihashcall(c13,10) n10=ihashcall(cw,10)
n12=ihashcall(c13,12) n12=ihashcall(cw,12)
n22=ihashcall(c13,22) n22=ihashcall(cw,22)
do i=1,nzhash do i=1,nzhash
if(ihash22(i).eq.n22) go to 900 !This one is already in the table if(ihash22(i).eq.n22) go to 900 !This one is already in the table
enddo enddo
@ -124,7 +115,7 @@ subroutine save_hash_call(c13,n10,n12,n22)
ihash10(1)=n10 ihash10(1)=n10
ihash12(1)=n12 ihash12(1)=n12
ihash22(1)=n22 ihash22(1)=n22
callsign(1)=c13 callsign(1)=cw
if(nzhash.lt.MAXHASH) nzhash=nzhash+1 if(nzhash.lt.MAXHASH) nzhash=nzhash+1
900 return 900 return
@ -448,9 +439,11 @@ subroutine unpack77(c77,msg,unpk77_success)
if(iflip.eq.0) then if(iflip.eq.0) then
call_1=call_3 call_1=call_3
call_2=adjustl(c11)//' ' call_2=adjustl(c11)//' '
call add_call_to_recent_calls(call_2)
else else
call_1=adjustl(c11)//' ' call_1=adjustl(c11)//' '
call_2=call_3 call_2=call_3
call add_call_to_recent_calls(call_1)
endif endif
if(icq.eq.0) then if(icq.eq.0) then
if(nrpt.eq.0) msg=trim(call_1)//' '//trim(call_2) if(nrpt.eq.0) msg=trim(call_1)//' '//trim(call_2)
@ -662,7 +655,7 @@ subroutine unpack28(n28_0,c13,success)
c13=adjustl(c13) c13=adjustl(c13)
900 i0=index(c13,' ') 900 i0=index(c13,' ')
if(i0.lt.len(trim(c13))) then if(i0.ne.0 .and. i0.lt.len(trim(c13))) then
c13='QU1RK' c13='QU1RK'
success=.false. success=.false.
endif endif
@ -1218,6 +1211,9 @@ subroutine add_call_to_recent_calls(callsign)
recent_calls(1)=callsign recent_calls(1)=callsign
endif endif
! Make sure that callsign is hashed
call save_hash_call(callsign,n10,n12,n22)
return return
end subroutine add_call_to_recent_calls end subroutine add_call_to_recent_calls

View File

@ -67,7 +67,19 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
else else
open(13,file=trim(temp_dir)//'/decoded.txt',status='unknown',iostat=ios) open(13,file=trim(temp_dir)//'/decoded.txt',status='unknown',iostat=ios)
endif endif
if(ios.ne.0) then
nfail=nfail+1
if(nfail.le.3) then
call sleep_msec(10)
go to 10
endif
endif
if(params%nmode.eq.8) then if(params%nmode.eq.8) then
! We're in FT8 mode
if(ncontest.eq.5) then
! Fox mode: initialize and open houndcallers.txt
inquire(file=trim(temp_dir)//'/houndcallers.txt',exist=ex) inquire(file=trim(temp_dir)//'/houndcallers.txt',exist=ex)
if(.not.ex) then if(.not.ex) then
c2fox=' ' c2fox=' '
@ -81,16 +93,6 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
open(19,file=trim(temp_dir)//'/houndcallers.txt',status='unknown') open(19,file=trim(temp_dir)//'/houndcallers.txt',status='unknown')
endif endif
if(ios.ne.0) then
nfail=nfail+1
if(nfail.le.3) then
call sleep_msec(10)
go to 10
endif
endif
if(params%nmode.eq.8) then
! We're in FT8 mode
call timer('decft8 ',0) call timer('decft8 ',0)
newdat=params%newdat newdat=params%newdat
ncontest=iand(params%nexp_decode,7) ncontest=iand(params%nexp_decode,7)
@ -106,6 +108,9 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
n30max=maxval(n30fox(1:nfox)) n30max=maxval(n30fox(1:nfox))
endif endif
j=0 j=0
if(ncontest.eq.5) then
! Fox mode: save decoded Hound calls for possible selection by FoxOp
rewind 19 rewind 19
if(nfox.eq.0) then if(nfox.eq.0) then
endfile 19 endfile 19
@ -134,6 +139,7 @@ subroutine multimode_decoder(ss,id2,params,nfsample)
nfox=j nfox=j
flush(19) flush(19)
endif endif
endif
go to 800 go to 800
endif endif

View File

@ -398,12 +398,8 @@ subroutine ft8b_2(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,lapon,lapcqonly, &
if(ndepth.eq.3 .and. nharderrors.lt.0) then if(ndepth.eq.3 .and. nharderrors.lt.0) then
ndeep=3 ndeep=3
if(abs(nfqso-f1).le.napwid .or. abs(nftx-f1).le.napwid) then if(abs(nfqso-f1).le.napwid .or. abs(nftx-f1).le.napwid) then
if((ipass.eq.3 .or. ipass.eq.4) .and. .not.nagain) then
ndeep=3
else
ndeep=4 ndeep=4
endif endif
endif
if(nagain) ndeep=5 if(nagain) ndeep=5
call timer('osd174_91 ',0) call timer('osd174_91 ',0)
call osd174_91(llrd,apmask,ndeep,message77,cw,nharderrors,dmin) call osd174_91(llrd,apmask,ndeep,message77,cw,nharderrors,dmin)

View File

@ -18,7 +18,6 @@ subroutine genft8_174_91(msg,i3,n3,msgsent,msgbits,itone)
n3=-1 n3=-1
call pack77(msg,i3,n3,c77) call pack77(msg,i3,n3,c77)
call unpack77(c77,msgsent,unpk77_success) call unpack77(c77,msgsent,unpk77_success)
read(c77,'(77i1)',err=1) msgbits read(c77,'(77i1)',err=1) msgbits
go to 2 go to 2
1 write(81,*) msg,c77 ; flush(81) 1 write(81,*) msg,c77 ; flush(81)

View File

@ -29,7 +29,7 @@ subroutine genmsk40(msg,msgsent,ichk,itone,itype)
10 irpt=i !Report index, 0-15 10 irpt=i !Report index, 0-15
if(ichk.lt.10000) then if(ichk.lt.10000) then
hashmsg=msg(2:i1-1) hashmsg=msg(2:i1-1)
call hash(hashmsg,22,ihash) call hash(hashmsg,37,ihash)
ihash=iand(ihash,4095) !12-bit hash ihash=iand(ihash,4095) !12-bit hash
ig=16*ihash + irpt !4-bit report ig=16*ihash + irpt !4-bit report
else else

View File

@ -46,6 +46,7 @@ subroutine genmsk_128_90(msg0,ichk,msgsent,i4tone,itype)
enddo enddo
endif endif
message(1:37)=' '
itype=1 itype=1
if(msg0(1:1).eq.'@') then !Generate a fixed tone if(msg0(1:1).eq.'@') then !Generate a fixed tone
read(msg0(2:5),*,end=1,err=1) nfreq !at specified frequency read(msg0(2:5),*,end=1,err=1) nfreq !at specified frequency
@ -54,24 +55,29 @@ subroutine genmsk_128_90(msg0,ichk,msgsent,i4tone,itype)
2 i4tone(1)=nfreq 2 i4tone(1)=nfreq
else else
message=msg0 message=msg0
do i=1, 37 do i=1, 37
if(ichar(message(i:i)).eq.0) then if(ichar(message(i:i)).eq.0) then
message(i:)=' ' message(i:37)=' '
exit exit
endif endif
enddo enddo
do i=1,37 !Strip leading blanks do i=1,37 !Strip leading blanks
if(message(1:1).ne.' ') exit if(message(1:1).ne.' ') exit
message=message(i+1:) message=message(i+1:)
enddo enddo
if(message(1:1).eq.'<') then if(message(1:1).eq.'<') then
i2=index(message,'>')
i1=0
if(i2.gt.0) i1=index(message(1:i2),' ')
if(i1.gt.0) then
call genmsk40(message,msgsent,ichk,i4tone,itype) call genmsk40(message,msgsent,ichk,i4tone,itype)
if(itype.lt.0) go to 999 if(itype.lt.0) go to 999
i4tone(41)=-40 i4tone(41)=-40
go to 999 go to 999
endif endif
endif
i3=-1 i3=-1
n3=-1 n3=-1

View File

@ -5,8 +5,8 @@ subroutine msk40decodeframe(c,mycall,hiscall,xsnr,bswl,nhasharray, &
parameter (NSPM=240) parameter (NSPM=240)
character*4 rpt(0:15) character*4 rpt(0:15)
character*6 mycall,hiscall,mycall0,hiscall0 character*12 mycall,hiscall,mycall0,hiscall0
character*22 hashmsg,msgreceived character*37 hashmsg,msgreceived
complex cb(42) complex cb(42)
complex cfac,cca complex cfac,cca
complex c(NSPM) complex c(NSPM)
@ -59,7 +59,7 @@ subroutine msk40decodeframe(c,mycall,hiscall,xsnr,bswl,nhasharray, &
hashmsg=trim(mycall)//' '//trim(hiscall) hashmsg=trim(mycall)//' '//trim(hiscall)
if( hashmsg .ne. ' ' .and. hiscall .ne. '' ) then ! protect against blank mycall/hiscall if( hashmsg .ne. ' ' .and. hiscall .ne. '' ) then ! protect against blank mycall/hiscall
call fmtmsg(hashmsg,iz) call fmtmsg(hashmsg,iz)
call hash(hashmsg,22,ihash) call hash(hashmsg,37,ihash)
ihash=iand(ihash,4095) ihash=iand(ihash,4095)
else else
ihash=9999 ! so that it can never match a received hash ihash=9999 ! so that it can never match a received hash

View File

@ -6,8 +6,8 @@ subroutine msk40spd(cbig,n,ntol,mycall,hiscall,bswl,nhasharray, &
use timer_module, only: timer use timer_module, only: timer
parameter (NSPM=240, MAXSTEPS=150, NFFT=NSPM, MAXCAND=5, NPATTERNS=6) parameter (NSPM=240, MAXSTEPS=150, NFFT=NSPM, MAXCAND=5, NPATTERNS=6)
character*6 mycall,hiscall character*12 mycall,hiscall
character*22 msgreceived character*37 msgreceived
complex cbig(n) complex cbig(n)
complex cdat(3*NSPM) !Analytic signal complex cdat(3*NSPM) !Analytic signal
complex c(NSPM) complex c(NSPM)

View File

@ -15,10 +15,10 @@ subroutine mskrtd(id2,nutc0,tsec,ntol,nrxfreq,ndepth,mycall,mygrid,hiscall, &
character*4 decsym !"&" for mskspd or "^" for long averages character*4 decsym !"&" for mskspd or "^" for long averages
character*37 msgreceived !Decoded message character*37 msgreceived !Decoded message
character*22 msgrx22 !Sh messages are returned as 22chars
character*37 msglast,msglastswl !Used for dupechecking character*37 msglast,msglastswl !Used for dupechecking
character*80 line !Formatted line with UTC dB T Freq Msg character*80 line !Formatted line with UTC dB T Freq Msg
character*12 mycall,hiscall character*12 mycall,hiscall
character*13 mycall13
character*6 mygrid character*6 mygrid
character*37 recent_shmsgs(NSHMEM) character*37 recent_shmsgs(NSHMEM)
character*512 datadir character*512 datadir
@ -55,7 +55,7 @@ subroutine mskrtd(id2,nutc0,tsec,ntol,nrxfreq,ndepth,mycall,mygrid,hiscall, &
1,1,1,1,1,1,1,0/ 1,1,1,1,1,1,1,0/
data xmc/2.0,4.5,2.5,3.5/ !Used to set time at center of averaging mask data xmc/2.0,4.5,2.5,3.5/ !Used to set time at center of averaging mask
save first,tsec0,nutc00,pnoise,cdat,msglast,msglastswl, & save first,tsec0,nutc00,pnoise,cdat,msglast,msglastswl, &
nsnrlast,nsnrlastswl,nhasharray,recent_shmsgs nsnrlast,nsnrlastswl,nhasharray,recent_shmsgs,mycall13
if(first) then if(first) then
tsec0=tsec tsec0=tsec
@ -71,11 +71,16 @@ subroutine mskrtd(id2,nutc0,tsec,ntol,nrxfreq,ndepth,mycall,mygrid,hiscall, &
msglastswl=' ' msglastswl=' '
nsnrlast=-99 nsnrlast=-99
nsnrlastswl=-99 nsnrlastswl=-99
mycall13=mycall//" "
call save_hash_call(mycall13,n10,n12,n22) ! Make sure that my callsign is in hashtable
first=.false. first=.false.
endif endif
fc=nrxfreq fc=nrxfreq
! Reset if mycall changes
if(mycall13(1:12).ne.mycall) first=.true.
! Dupe checking setup ! Dupe checking setup
if(nutc00.ne.nutc0 .or. tsec.lt.tsec0) then ! reset dupe checker if(nutc00.ne.nutc0 .or. tsec.lt.tsec0) then ! reset dupe checker
msglast=' ' msglast=' '
@ -119,9 +124,8 @@ subroutine mskrtd(id2,nutc0,tsec,ntol,nrxfreq,ndepth,mycall,mygrid,hiscall, &
call msk144spd(cdat,np,ntol,ndecodesuccess,msgreceived,fc,fest,tdec,navg,ct, & call msk144spd(cdat,np,ntol,ndecodesuccess,msgreceived,fc,fest,tdec,navg,ct, &
softbits) softbits)
if(ndecodesuccess.eq.0 .and. (bshmsg.or.bswl)) then if(ndecodesuccess.eq.0 .and. (bshmsg.or.bswl)) then
call msk40spd(cdat,np,ntol,mycall(1:6),hiscall(1:6),bswl,nhasharray, & call msk40spd(cdat,np,ntol,mycall,hiscall,bswl,nhasharray, &
ndecodesuccess,msgrx22,fc,fest,tdec,navg) ndecodesuccess,msgreceived,fc,fest,tdec,navg)
if( ndecodesuccess .ge. 1 ) msgreceived=msgrx22//' '
endif endif
if( ndecodesuccess .ge. 1 ) then if( ndecodesuccess .ge. 1 ) then
tdec=tsec+tdec tdec=tsec+tdec
@ -184,7 +188,12 @@ subroutine mskrtd(id2,nutc0,tsec,ntol,nrxfreq,ndepth,mycall,mygrid,hiscall, &
nsnr=nint(snr0) nsnr=nint(snr0)
bshdecode=.false. bshdecode=.false.
if( msgreceived(1:1) .eq. '<' ) bshdecode=.true. if( msgreceived(1:1) .eq. '<' ) then
i2=index(msgreceived,'>')
i1=0
if(i2.gt.0) i1=index(msgreceived(1:i2),' ')
if(i1.gt.0) bshdecode=.true.
endif
if(.not. bshdecode) then if(.not. bshdecode) then
call msk144signalquality(ct,snr0,fest,tdec,softbits,msgreceived,hiscall, & call msk144signalquality(ct,snr0,fest,tdec,softbits,msgreceived,hiscall, &

View File

@ -29,7 +29,7 @@ subroutine sync4(dat,jz,ntol,nfqso,mode,mode4,minwidth,dtx,dfx,snrx, &
df=0.5*11025.0/nfft df=0.5*11025.0/nfft
ftop=nfqso + 7*mode4*df ftop=nfqso + 7*mode4*df
if(ftop.gt.11025.0/4.0) then if(ftop.gt.11025.0/4.0) then
print*,'*** Rx Freq is set too high for this sybmode ***' print*,'*** Rx Freq is set too high for this submode ***'
go to 900 go to 900
endif endif

View File

@ -1,7 +1,7 @@
subroutine update_hasharray(nhasharray) subroutine update_hasharray(nhasharray)
use packjt77 use packjt77
character*22 hashmsg character*37 hashmsg
integer nhasharray(MAXRECENT,MAXRECENT) integer nhasharray(MAXRECENT,MAXRECENT)
nhasharray=-1 nhasharray=-1
@ -10,12 +10,12 @@ subroutine update_hasharray(nhasharray)
if( recent_calls(i)(1:1) .ne. ' ' .and. recent_calls(j)(1:1) .ne. ' ' ) then if( recent_calls(i)(1:1) .ne. ' ' .and. recent_calls(j)(1:1) .ne. ' ' ) then
hashmsg=trim(recent_calls(i))//' '//trim(recent_calls(j)) hashmsg=trim(recent_calls(i))//' '//trim(recent_calls(j))
call fmtmsg(hashmsg,iz) call fmtmsg(hashmsg,iz)
call hash(hashmsg,22,ihash) call hash(hashmsg,37,ihash)
ihash=iand(ihash,4095) ihash=iand(ihash,4095)
nhasharray(i,j)=ihash nhasharray(i,j)=ihash
hashmsg=trim(recent_calls(j))//' '//trim(recent_calls(i)) hashmsg=trim(recent_calls(j))//' '//trim(recent_calls(i))
call fmtmsg(hashmsg,iz) call fmtmsg(hashmsg,iz)
call hash(hashmsg,22,ihash) call hash(hashmsg,37,ihash)
ihash=iand(ihash,4095) ihash=iand(ihash,4095)
nhasharray(j,i)=ihash nhasharray(j,i)=ihash
endif endif

View File

@ -205,8 +205,15 @@ QByteArray ADIF::QSOToADIF(QString const& hisCall, QString const& hisGrid, QStri
if(comments!="") t += " <comment:" + QString::number(comments.length()) + ">" + comments; if(comments!="") t += " <comment:" + QString::number(comments.length()) + ">" + comments;
if(name!="") t += " <name:" + QString::number(name.length()) + ">" + name; if(name!="") t += " <name:" + QString::number(name.length()) + ">" + name;
if(operator_call!="") t+=" <operator:" + QString::number(operator_call.length()) + ">" + operator_call; if(operator_call!="") t+=" <operator:" + QString::number(operator_call.length()) + ">" + operator_call;
if(xSent!="") t += " <STX_STRING:" + QString::number(xSent.length()) + ">" + xSent; if(xRcvd!="") {
if(xRcvd!="") t += " <SRX_STRING:" + QString::number(xRcvd.length()) + ">" + xRcvd; QString t1="";
if(xRcvd.split(" ").size()==2) t1=xRcvd.split(" ").at(1);
if(t1.toInt()>0) {
t += " <SRX:" + QString::number(t1.length()) + ">" + t1;
} else {
t += " <STATE:" + QString::number(t1.length()) + ">" + t1;
}
}
return t.toLatin1(); return t.toLatin1();
} }

View File

@ -92,6 +92,8 @@ void LogQSO::initLogQSO(QString const& hisCall, QString const& hisGrid, QString
m_myGrid=myGrid; m_myGrid=myGrid;
ui->band->setText (m_config->bands ()->find (dialFreq)); ui->band->setText (m_config->bands ()->find (dialFreq));
ui->loggedOperator->setText(opCall); ui->loggedOperator->setText(opCall);
ui->exchSent->setText(m_xSent);
ui->exchRcvd->setText(m_xRcvd);
if(bFox or bAutoLog) { if(bFox or bAutoLog) {
accept(); accept();
} else { } else {

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>377</width> <width>377</width>
<height>257</height> <height>287</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -16,7 +16,7 @@
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_11"> <layout class="QVBoxLayout" name="verticalLayout_5">
<item> <item>
<widget class="QLabel" name="label"> <widget class="QLabel" name="label">
<property name="font"> <property name="font">
@ -390,6 +390,57 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Exch sent</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="exchSent">
<property name="maximumSize">
<size>
<width>120</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_4">
<property name="text">
<string>Rcvd</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="exchRcvd">
<property name="maximumSize">
<size>
<width>120</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
</layout>
</item>
<item> <item>
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
@ -397,7 +448,7 @@
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>20</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>

View File

@ -17,13 +17,10 @@
#include <QStandardPaths> #include <QStandardPaths>
#include <QStringList> #include <QStringList>
#include <QLockFile> #include <QLockFile>
#include <QStack>
#include <QSplashScreen> #include <QSplashScreen>
#if QT_VERSION >= 0x050200
#include <QCommandLineParser> #include <QCommandLineParser>
#include <QCommandLineOption> #include <QCommandLineOption>
#endif
#include "revision_utils.hpp" #include "revision_utils.hpp"
#include "MetaDataRegistry.hpp" #include "MetaDataRegistry.hpp"
@ -54,38 +51,12 @@ namespace
qsrand (seed); // this is good for rand() as well qsrand (seed); // this is good for rand() as well
} }
} seeding; } seeding;
class MessageTimestamper
{
public:
MessageTimestamper ()
{
prior_handlers_.push (qInstallMessageHandler (message_handler));
}
~MessageTimestamper ()
{
if (prior_handlers_.size ()) qInstallMessageHandler (prior_handlers_.pop ());
}
private:
static void message_handler (QtMsgType type, QMessageLogContext const& context, QString const& msg)
{
QtMessageHandler handler {prior_handlers_.top ()};
if (handler)
{
handler (type, context,
QDateTime::currentDateTimeUtc ().toString ("yy-MM-ddTHH:mm:ss.zzzZ: ") + msg);
}
}
static QStack<QtMessageHandler> prior_handlers_;
};
QStack<QtMessageHandler> MessageTimestamper::prior_handlers_;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// Add timestamps to all debug messages // Add timestamps to all debug messages
MessageTimestamper message_timestamper; qSetMessagePattern ("[%{time yyyyMMdd HH:mm:ss.zzz t} %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{message}");
init_random_seed (); init_random_seed ();
@ -108,7 +79,6 @@ int main(int argc, char *argv[])
a.setApplicationName ("WSJT-X"); a.setApplicationName ("WSJT-X");
a.setApplicationVersion (version ()); a.setApplicationVersion (version ());
#if QT_VERSION >= 0x050200
QCommandLineParser parser; QCommandLineParser parser;
parser.setApplicationDescription ("\n" PROJECT_SUMMARY_DESCRIPTION); parser.setApplicationDescription ("\n" PROJECT_SUMMARY_DESCRIPTION);
auto help_option = parser.addHelpOption (); auto help_option = parser.addHelpOption ();
@ -210,11 +180,11 @@ int main(int argc, char *argv[])
} }
} }
} }
#endif
#if WSJT_QDEBUG_TO_FILE #if WSJT_QDEBUG_TO_FILE
// Open a trace file // Open a trace file
TraceFile trace_file {temp_dir.absoluteFilePath (a.applicationName () + "_trace.log")}; TraceFile trace_file {temp_dir.absoluteFilePath (a.applicationName () + "_trace.log")};
qSetMessagePattern ("[%{time yyyyMMdd HH:mm:ss.zzz t} %{if-debug}D%{endif}%{if-info}I%{endif}%{if-warning}W%{endif}%{if-critical}C%{endif}%{if-fatal}F%{endif}] %{file}:%{line} - %{message}");
qDebug () << program_title (revision ()) + " - Program startup"; qDebug () << program_title (revision ()) + " - Program startup";
#endif #endif

View File

@ -60,6 +60,7 @@
#include "CallsignValidator.hpp" #include "CallsignValidator.hpp"
#include "ExchangeValidator.hpp" #include "ExchangeValidator.hpp"
#include "EqualizationToolsDialog.hpp" #include "EqualizationToolsDialog.hpp"
#include "LotWUsers.hpp"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "moc_mainwindow.cpp" #include "moc_mainwindow.cpp"
@ -163,7 +164,6 @@ int fast_jhpeak {0};
int fast_jh2 {0}; int fast_jh2 {0};
int narg[15]; int narg[15];
QVector<QColor> g_ColorTbl; QVector<QColor> g_ColorTbl;
QHash<QString,int> m_LoTW;
namespace namespace
{ {
@ -204,7 +204,7 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_configurations_button {0}, m_configurations_button {0},
m_settings {multi_settings->settings ()}, m_settings {multi_settings->settings ()},
ui(new Ui::MainWindow), ui(new Ui::MainWindow),
m_config {temp_directory, m_settings, this}, m_config {&m_network_manager, temp_directory, m_settings, this},
m_WSPR_band_hopping {m_settings, &m_config, this}, m_WSPR_band_hopping {m_settings, &m_config, this},
m_WSPR_tx_next {false}, m_WSPR_tx_next {false},
m_rigErrorMessageBox {MessageBox::Critical, tr ("Rig Control Error") m_rigErrorMessageBox {MessageBox::Critical, tr ("Rig Control Error")
@ -387,6 +387,8 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
ui->dxGridEntry->setValidator (new MaidenheadLocatorValidator {this}); ui->dxGridEntry->setValidator (new MaidenheadLocatorValidator {this});
ui->dxCallEntry->setValidator (new CallsignValidator {this}); ui->dxCallEntry->setValidator (new CallsignValidator {this});
ui->sbTR->values ({5, 10, 15, 30}); ui->sbTR->values ({5, 10, 15, 30});
ui->decodedTextBrowser->set_configuration (&m_config);
ui->decodedTextBrowser2->set_configuration (&m_config);
m_baseCall = Radio::base_callsign (m_config.my_callsign ()); m_baseCall = Radio::base_callsign (m_config.my_callsign ());
m_opCall = m_config.opCall(); m_opCall = m_config.opCall();
@ -556,6 +558,10 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_equalizationToolsDialog->show (); m_equalizationToolsDialog->show ();
}); });
connect (&m_config.lotw_users (), &LotWUsers::LotW_users_error, this, [this] (QString const& reason) {
MessageBox::warning_message (this, tr ("Error Loading LotW Users Data"), reason);
}, Qt::QueuedConnection);
QButtonGroup* txMsgButtonGroup = new QButtonGroup {this}; QButtonGroup* txMsgButtonGroup = new QButtonGroup {this};
txMsgButtonGroup->addButton(ui->txrb1,1); txMsgButtonGroup->addButton(ui->txrb1,1);
txMsgButtonGroup->addButton(ui->txrb2,2); txMsgButtonGroup->addButton(ui->txrb2,2);
@ -722,6 +728,8 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
m_msg[0][0]=0; m_msg[0][0]=0;
ui->labDXped->setVisible(false); ui->labDXped->setVisible(false);
ui->labDXped->setStyleSheet("QLabel {background-color: red; color: white;}"); ui->labDXped->setStyleSheet("QLabel {background-color: red; color: white;}");
ui->labNextCall->setText("");
ui->labNextCall->setVisible(false);
for(int i=0; i<28; i++) { //Initialize dBm values for(int i=0; i<28; i++) { //Initialize dBm values
float dbm=(10.0*i)/3.0 - 30.0; float dbm=(10.0*i)/3.0 - 30.0;
@ -741,7 +749,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
ui->decodedTextLabel->setText(t); ui->decodedTextLabel->setText(t);
ui->decodedTextLabel2->setText(t); ui->decodedTextLabel2->setText(t);
readSettings(); //Restore user's setup parameters readSettings(); //Restore user's setup parameters
setColorHighlighting(); //Set the color highlighting scheme for decoded text.
m_audioThread.start (m_audioThreadPriority); m_audioThread.start (m_audioThreadPriority);
#ifdef WIN32 #ifdef WIN32
@ -920,31 +927,6 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
ui->cbMenus->setChecked(false); ui->cbMenus->setChecked(false);
} }
QFile f{m_config.data_dir().absoluteFilePath ("lotw-user-activity.csv")};
if(f.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream s(&f);
QString line,call;
int nLoTW=0;
int i1;
QDateTime now=QDateTime::currentDateTime();
QDateTime callDateTime;
// Read and process the file of LoTW-active stations
while(!s.atEnd()) {
line=s.readLine();
i1=line.indexOf(",");
call=line.left(i1);
line=line.mid(i1+1);
i1=line.indexOf(",");
callDateTime=QDateTime::fromString(line.left(i1),"yyyy-MM-dd");
int ndays=callDateTime.daysTo(now);
if(ndays < 366) {
nLoTW++;
m_LoTW[call]=ndays;
}
}
f.close();
}
// this must be the last statement of constructor // this must be the last statement of constructor
if (!m_valid) throw std::runtime_error {"Fatal initialization exception"}; if (!m_valid) throw std::runtime_error {"Fatal initialization exception"};
} }
@ -952,14 +934,14 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
void MainWindow::not_GA_warning_message () void MainWindow::not_GA_warning_message ()
{ {
QDateTime now=QDateTime::currentDateTime(); QDateTime now=QDateTime::currentDateTime();
QDateTime timeout=QDateTime(QDate(2018,10,31)); QDateTime timeout=QDateTime(QDate(2018,11,30));
MessageBox::critical_message (this, MessageBox::critical_message (this,
"This version of WSJT-X is a beta-level Release Candidate.\n\n" "This version of WSJT-X is a beta-level Release Candidate.\n\n"
"On-the-air use carries an obligation to report problems\n" "On-the-air use carries an obligation to report problems\n"
"to the WSJT Development group and to upgrade to a GA\n" "to the WSJT Development group and to upgrade to a GA\n"
"(General Availability) release when it becomes available.\n\n" "(General Availability) release when it becomes available.\n\n"
"This version cannot be used after October 31, 2018\n\n"); "This version cannot be used after November 30, 2018\n\n");
if(now.daysTo(timeout) < 0) Q_EMIT finished(); if(now.daysTo(timeout) < 0) Q_EMIT finished();
} }
@ -1108,7 +1090,8 @@ void MainWindow::readSettings()
ui->cbFirst->setChecked(m_settings->value("CallFirst",true).toBool()); ui->cbFirst->setChecked(m_settings->value("CallFirst",true).toBool());
ui->comboBoxHoundSort->setCurrentIndex(m_settings->value("HoundSort",3).toInt()); ui->comboBoxHoundSort->setCurrentIndex(m_settings->value("HoundSort",3).toInt());
ui->sbNlist->setValue(m_settings->value("FoxNlist",12).toInt()); ui->sbNlist->setValue(m_settings->value("FoxNlist",12).toInt());
ui->sbNslots->setValue(m_settings->value("FoxNslots",5).toInt()); m_Nslots=m_settings->value("FoxNslots",5).toInt();
ui->sbNslots->setValue(m_Nslots);
ui->sbMax_dB->setValue(m_settings->value("FoxMaxDB",30).toInt()); ui->sbMax_dB->setValue(m_settings->value("FoxMaxDB",30).toInt());
m_settings->endGroup(); m_settings->endGroup();
@ -1188,8 +1171,8 @@ void MainWindow::readSettings()
m_audioThreadPriority = static_cast<QThread::Priority> (m_settings->value ("Audio/ThreadPriority", QThread::HighPriority).toInt () % 8); m_audioThreadPriority = static_cast<QThread::Priority> (m_settings->value ("Audio/ThreadPriority", QThread::HighPriority).toInt () % 8);
m_settings->endGroup (); m_settings->endGroup ();
if (displayMsgAvg) on_actionMessage_averaging_triggered();
setContestType(); setContestType();
if(displayMsgAvg) on_actionMessage_averaging_triggered();
} }
void MainWindow::setContestType() void MainWindow::setContestType()
@ -1220,7 +1203,7 @@ void MainWindow::setDecodedTextFont (QFont const& font)
ui->decodedTextBrowser->setContentFont (font); ui->decodedTextBrowser->setContentFont (font);
ui->decodedTextBrowser2->setContentFont (font); ui->decodedTextBrowser2->setContentFont (font);
ui->textBrowser4->setContentFont(font); ui->textBrowser4->setContentFont(font);
ui->textBrowser4->displayFoxToBeCalled(" ","#ffffff"); ui->textBrowser4->displayFoxToBeCalled(" ");
ui->textBrowser4->setText(""); ui->textBrowser4->setText("");
auto style_sheet = "QLabel {" + font_as_stylesheet (font) + '}'; auto style_sheet = "QLabel {" + font_as_stylesheet (font) + '}';
ui->decodedTextLabel->setStyleSheet (ui->decodedTextLabel->styleSheet () + style_sheet); ui->decodedTextLabel->setStyleSheet (ui->decodedTextLabel->styleSheet () + style_sheet);
@ -1527,11 +1510,13 @@ void MainWindow::fastSink(qint64 frames)
int RxFreq=ui->RxFreqSpinBox->value (); int RxFreq=ui->RxFreqSpinBox->value ();
int nTRpDepth=m_TRperiod + 1000*(m_ndepth & 3); int nTRpDepth=m_TRperiod + 1000*(m_ndepth & 3);
qint64 ms0 = QDateTime::currentMSecsSinceEpoch(); qint64 ms0 = QDateTime::currentMSecsSinceEpoch();
strncpy(dec_data.params.mycall, (m_baseCall+" ").toLatin1(),12); // strncpy(dec_data.params.mycall, (m_baseCall+" ").toLatin1(),12);
strncpy(dec_data.params.mycall,(m_config.my_callsign () + " ").toLatin1(),12);
QString hisCall {ui->dxCallEntry->text ()}; QString hisCall {ui->dxCallEntry->text ()};
bool bshmsg=ui->cbShMsgs->isChecked(); bool bshmsg=ui->cbShMsgs->isChecked();
bool bswl=ui->cbSWL->isChecked(); bool bswl=ui->cbSWL->isChecked();
strncpy(dec_data.params.hiscall,(Radio::base_callsign (hisCall) + " ").toLatin1 ().constData (), 12); // strncpy(dec_data.params.hiscall,(Radio::base_callsign (hisCall) + " ").toLatin1 ().constData (), 12);
strncpy(dec_data.params.hiscall,(hisCall + " ").toLatin1 ().constData (), 12);
strncpy(dec_data.params.mygrid, (m_config.my_grid()+" ").toLatin1(),6); strncpy(dec_data.params.mygrid, (m_config.my_grid()+" ").toLatin1(),6);
QString dataDir; QString dataDir;
dataDir = m_config.writeable_data_dir ().absolutePath (); dataDir = m_config.writeable_data_dir ().absolutePath ();
@ -1705,23 +1690,8 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog
} }
m_opCall=m_config.opCall(); m_opCall=m_config.opCall();
} }
setColorHighlighting();
} }
void MainWindow::setColorHighlighting()
{
//Inform the decoded text windows about our color-highlighting scheme.
ui->decodedTextBrowser->setDecodedTextColors(m_config.color_CQ(),m_config.color_MyCall(),
m_config.color_DXCC(),m_config.color_DXCCband(),m_config.color_NewCall(),
m_config.color_NewCallBand(),m_config.color_NewGrid(),m_config.color_NewGridBand(),
m_config.color_TxMsg(),m_config.color_LoTW());
ui->decodedTextBrowser2->setDecodedTextColors(m_config.color_CQ(),m_config.color_MyCall(),
m_config.color_DXCC(),m_config.color_DXCCband(),m_config.color_NewCall(),
m_config.color_NewCallBand(),m_config.color_NewGrid(),m_config.color_NewGridBand(),
m_config.color_TxMsg(),m_config.color_LoTW());
}
void MainWindow::on_monitorButton_clicked (bool checked) void MainWindow::on_monitorButton_clicked (bool checked)
{ {
if (!m_transmitting) { if (!m_transmitting) {
@ -1839,6 +1809,9 @@ void MainWindow::keyPressEvent (QKeyEvent * e)
} }
} }
break; break;
case Qt::Key_Escape:
on_stopTxButton_clicked();
return;
case Qt::Key_F1: case Qt::Key_F1:
on_actionOnline_User_Guide_triggered(); on_actionOnline_User_Guide_triggered();
return; return;
@ -1863,6 +1836,11 @@ void MainWindow::keyPressEvent (QKeyEvent * e)
on_actionOpen_next_in_directory_triggered(); on_actionOpen_next_in_directory_triggered();
return; return;
case Qt::Key_F11: case Qt::Key_F11:
if((e->modifiers() & Qt::ControlModifier) and (e->modifiers() & Qt::ShiftModifier)) {
m_bandEdited = true;
band_changed(m_freqNominal-2000);
// qDebug() << "Down" << m_freqNominal;
} else {
n=11; n=11;
if(e->modifiers() & Qt::ControlModifier) n+=100; if(e->modifiers() & Qt::ControlModifier) n+=100;
if(e->modifiers() & Qt::ShiftModifier) { if(e->modifiers() & Qt::ShiftModifier) {
@ -1870,8 +1848,14 @@ void MainWindow::keyPressEvent (QKeyEvent * e)
} else{ } else{
bumpFqso(n); bumpFqso(n);
} }
}
return; return;
case Qt::Key_F12: case Qt::Key_F12:
if((e->modifiers() & Qt::ControlModifier) and (e->modifiers() & Qt::ShiftModifier)) {
m_bandEdited = true;
band_changed(m_freqNominal+2000);
// qDebug() << "Up " << m_freqNominal;
} else {
n=12; n=12;
if(e->modifiers() & Qt::ControlModifier) n+=100; if(e->modifiers() & Qt::ControlModifier) n+=100;
if(e->modifiers() & Qt::ShiftModifier) { if(e->modifiers() & Qt::ShiftModifier) {
@ -1879,6 +1863,7 @@ void MainWindow::keyPressEvent (QKeyEvent * e)
} else { } else {
bumpFqso(n); bumpFqso(n);
} }
}
return; return;
case Qt::Key_X: case Qt::Key_X:
if(e->modifiers() & Qt::AltModifier) { if(e->modifiers() & Qt::AltModifier) {
@ -1939,7 +1924,13 @@ void MainWindow::keyPressEvent (QKeyEvent * e)
return; return;
} }
break; break;
} case Qt::Key_PageUp:
break;
case Qt::Key_PageDown:
band_changed(m_freqNominal-2000);
qDebug() << "Down" << m_freqNominal;
break; }
QMainWindow::keyPressEvent (e); QMainWindow::keyPressEvent (e);
} }
@ -2187,7 +2178,7 @@ void MainWindow::closeEvent(QCloseEvent * e)
m_prefixes.reset (); m_prefixes.reset ();
m_shortcuts.reset (); m_shortcuts.reset ();
m_mouseCmnds.reset (); m_mouseCmnds.reset ();
m_colorHighlighting.reset(); m_colorHighlighting.reset ();
if(m_mode!="MSK144" and m_mode!="FT8") killFile(); if(m_mode!="MSK144" and m_mode!="FT8") killFile();
float sw=0.0; float sw=0.0;
int nw=400; int nw=400;
@ -2224,6 +2215,12 @@ void MainWindow::on_actionFT8_DXpedition_Mode_User_Guide_triggered()
{ {
QDesktopServices::openUrl (QUrl {"http://physics.princeton.edu/pulsar/k1jt/FT8_DXpedition_Mode.pdf"}); QDesktopServices::openUrl (QUrl {"http://physics.princeton.edu/pulsar/k1jt/FT8_DXpedition_Mode.pdf"});
} }
void MainWindow::on_actionQuick_Start_Guide_v2_triggered()
{
QDesktopServices::openUrl (QUrl {"https://physics.princeton.edu/pulsar/k1jt/Quick_Start_WSJT-X_2.0.pdf"});
}
void MainWindow::on_actionOnline_User_Guide_triggered() //Display manual void MainWindow::on_actionOnline_User_Guide_triggered() //Display manual
{ {
#if defined (CMAKE_BUILD) #if defined (CMAKE_BUILD)
@ -2395,16 +2392,14 @@ void MainWindow::on_actionFox_Log_triggered()
void MainWindow::on_actionColors_triggered() void MainWindow::on_actionColors_triggered()
{ {
if (!m_colorHighlighting) { if (!m_colorHighlighting)
m_colorHighlighting.reset (new ColorHighlighting {m_settings}); {
m_colorHighlighting.reset (new ColorHighlighting {m_settings, m_config.decode_highlighting ()});
connect (&m_config, &Configuration::decode_highlighting_changed, m_colorHighlighting.data (), &ColorHighlighting::set_items);
} }
m_colorHighlighting->showNormal(); m_colorHighlighting->showNormal ();
m_colorHighlighting->raise (); m_colorHighlighting->raise ();
m_colorHighlighting->activateWindow (); m_colorHighlighting->activateWindow ();
m_colorHighlighting->colorHighlightlingSetup(m_config.color_CQ(),m_config.color_MyCall(),
m_config.color_DXCC(),m_config.color_DXCCband(),m_config.color_NewCall(),
m_config.color_NewCallBand(),m_config.color_NewGrid(),m_config.color_NewGridBand(),
m_config.color_TxMsg(),m_config.color_LoTW());
} }
void MainWindow::on_actionMessage_averaging_triggered() void MainWindow::on_actionMessage_averaging_triggered()
@ -2945,12 +2940,17 @@ void MainWindow::readFromStdout() //readFromStdout
m_blankLine = false; m_blankLine = false;
} }
DecodedText decodedtext {QString::fromUtf8(t.constData()).remove(QRegularExpression {"\r|\n"})}; DecodedText decodedtext0 {QString::fromUtf8(t.constData())
.remove(QRegularExpression {"\r|\n"})};
DecodedText decodedtext {QString::fromUtf8(t.constData())
.remove(QRegularExpression {"\r|\n"}).remove("TU; ")};
if(m_mode=="FT8" and m_config.bFox() and if(m_mode=="FT8" and m_config.bFox() and
(decodedtext.string().contains("R+") or decodedtext.string().contains("R-"))) { (decodedtext.string().contains("R+") or decodedtext.string().contains("R-"))) {
auto for_us = decodedtext.string().contains(" " + m_config.my_callsign() + " ") or auto for_us = decodedtext.string().contains(" " + m_config.my_callsign() + " ") or
decodedtext.string().contains(" "+m_baseCall) or decodedtext.string().contains(" "+m_baseCall) or
decodedtext.string().contains(m_baseCall+" "); decodedtext.string().contains(m_baseCall+" ") or
decodedtext.string().contains(" <" + m_config.my_callsign() + "> ");
if(decodedtext.string().contains(" DE ")) for_us=true; //Hound with compound callsign if(decodedtext.string().contains(" DE ")) for_us=true; //Hound with compound callsign
if(for_us) { if(for_us) {
QString houndCall,houndGrid; QString houndCall,houndGrid;
@ -2958,7 +2958,8 @@ void MainWindow::readFromStdout() //readFromStdout
foxRxSequencer(decodedtext.string(),houndCall,houndGrid); foxRxSequencer(decodedtext.string(),houndCall,houndGrid);
} }
} }
//Left (Band activity) window
//Left (Band activity) window
if(!bAvgMsg) { if(!bAvgMsg) {
if(m_mode=="FT8" and m_config.bFox()) { if(m_mode=="FT8" and m_config.bFox()) {
if(!m_bDisplayedOnce) { if(!m_bDisplayedOnce) {
@ -2969,13 +2970,13 @@ void MainWindow::readFromStdout() //readFromStdout
m_bDisplayedOnce=true; m_bDisplayedOnce=true;
} }
} else { } else {
ui->decodedTextBrowser->displayDecodedText(decodedtext,m_baseCall,m_config.DXCC(), ui->decodedTextBrowser->displayDecodedText(decodedtext0,m_baseCall,m_config.DXCC(),
m_logBook,m_currentBand,m_config.ppfx(), m_logBook,m_currentBand,m_config.ppfx(),
(ui->cbCQonly->isVisible() and ui->cbCQonly->isChecked())); (ui->cbCQonly->isVisible() and ui->cbCQonly->isChecked()));
} }
} }
//Right (Rx Frequency) window //Right (Rx Frequency) window
bool bDisplayRight=bAvgMsg; bool bDisplayRight=bAvgMsg;
int audioFreq=decodedtext.frequencyOffset(); int audioFreq=decodedtext.frequencyOffset();
@ -3004,7 +3005,7 @@ void MainWindow::readFromStdout() //readFromStdout
if (bDisplayRight) { if (bDisplayRight) {
// This msg is within 10 hertz of our tuned frequency, or a JT4 or JT65 avg, // This msg is within 10 hertz of our tuned frequency, or a JT4 or JT65 avg,
// or contains MyCall // or contains MyCall
ui->decodedTextBrowser2->displayDecodedText(decodedtext,m_baseCall,m_config.DXCC(), ui->decodedTextBrowser2->displayDecodedText(decodedtext0,m_baseCall,m_config.DXCC(),
m_logBook,m_currentBand,m_config.ppfx()); m_logBook,m_currentBand,m_config.ppfx());
if(m_mode!="JT4") { if(m_mode!="JT4") {
@ -3058,8 +3059,9 @@ void MainWindow::readFromStdout() //readFromStdout
//### I think this is where we are preventing Hounds from spotting Fox ### //### I think this is where we are preventing Hounds from spotting Fox ###
if(m_mode!="FT8" or !m_config.bHound()) { if(m_mode!="FT8" or !m_config.bHound()) {
if(m_mode=="FT8" or m_mode=="QRA64" or m_mode=="JT4" or m_mode=="JT65" or if(m_mode=="FT8" or m_mode=="QRA64" or m_mode=="JT4" or m_mode=="JT65" or m_mode=="JT9") {
m_mode=="JT9") auto_sequence (decodedtext, 25, 50); auto_sequence (decodedtext, 25, 50);
}
postDecode (true, decodedtext.string ()); postDecode (true, decodedtext.string ());
// find and extract any report for myCall, but save in m_rptRcvd only if it's from DXcall // find and extract any report for myCall, but save in m_rptRcvd only if it's from DXcall
@ -3132,7 +3134,7 @@ void MainWindow::auto_sequence (DecodedText const& message, unsigned start_toler
} }
} }
bool bEU_VHF_w2=(nrpt>=520001 and nrpt<=594000); bool bEU_VHF_w2=(nrpt>=520001 and nrpt<=594000);
if(bEU_VHF_w2) m_xRcvd=message.string().left(45).trimmed().right(13); if(bEU_VHF_w2) m_xRcvd=message.string().trimmed().right(13);
if (m_auto if (m_auto
&& (m_QSOProgress==REPLYING or (!ui->tx1->isEnabled () and m_QSOProgress==REPORT)) && (m_QSOProgress==REPLYING or (!ui->tx1->isEnabled () and m_QSOProgress==REPORT))
&& qAbs (ui->TxFreqSpinBox->value () - df) <= int (stop_tolerance) && qAbs (ui->TxFreqSpinBox->value () - df) <= int (stop_tolerance)
@ -3335,13 +3337,9 @@ void MainWindow::guiUpdate()
auto const& message = tr ("Please choose another Tx frequency." auto const& message = tr ("Please choose another Tx frequency."
" WSJT-X will not knowingly transmit another" " WSJT-X will not knowingly transmit another"
" mode in the WSPR sub-band on 30m."); " mode in the WSPR sub-band on 30m.");
#if QT_VERSION >= 0x050400
QTimer::singleShot (0, [=] { // don't block guiUpdate QTimer::singleShot (0, [=] { // don't block guiUpdate
MessageBox::warning_message (this, tr ("WSPR Guard Band"), message); MessageBox::warning_message (this, tr ("WSPR Guard Band"), message);
}); });
#else
MessageBox::warning_message (this, tr ("WSPR Guard Band"), message);
#endif
} }
} }
@ -3356,13 +3354,9 @@ void MainWindow::guiUpdate()
auto const& message = tr ("Please choose another dial frequency." auto const& message = tr ("Please choose another dial frequency."
" WSJT-X will not operate in Fox mode" " WSJT-X will not operate in Fox mode"
" in the standard FT8 sub-bands."); " in the standard FT8 sub-bands.");
#if QT_VERSION >= 0x050400
QTimer::singleShot (0, [=] { // don't block guiUpdate QTimer::singleShot (0, [=] { // don't block guiUpdate
MessageBox::warning_message (this, tr ("Fox Mode warning"), message); MessageBox::warning_message (this, tr ("Fox Mode warning"), message);
}); });
#else
MessageBox::warning_message (this, tr ("Fox Mode warning"), message);
#endif
break; break;
} }
} }
@ -3582,7 +3576,6 @@ void MainWindow::guiUpdate()
m_xSent=t.at(n-2) + " " + t.at(n-1); m_xSent=t.at(n-2) + " " + t.at(n-1);
} }
} }
} }
if(m_isync==1) msgsent[22]=0; if(m_isync==1) msgsent[22]=0;
if(m_isync==2) msgsent[37]=0; if(m_isync==2) msgsent[37]=0;
@ -3631,13 +3624,14 @@ void MainWindow::guiUpdate()
if(m_config.id_after_73 ()) { if(m_config.id_after_73 ()) {
icw[0] = m_ncw; icw[0] = m_ncw;
} }
if ((m_config.prompt_to_log() or m_config.autoLog()) && !m_tune) { if((m_config.prompt_to_log() or m_config.autoLog()) && !m_tune) logQSOTimer.start(0);
logQSOTimer.start(0);
}
} }
bool b=(m_mode=="FT8") and ui->cbAutoSeq->isChecked(); bool b=(m_mode=="FT8") and ui->cbAutoSeq->isChecked();
if(is_73 and (m_config.disable_TX_on_73() or b)) { if(is_73 and (m_config.disable_TX_on_73() or b)) {
if(m_nextCall!="") {
useNextCall();
} else {
auto_tx_mode (false); auto_tx_mode (false);
if(b) { if(b) {
m_ntx=6; m_ntx=6;
@ -3645,6 +3639,7 @@ void MainWindow::guiUpdate()
m_QSOProgress = CALLING; m_QSOProgress = CALLING;
} }
} }
}
if(m_config.id_interval () >0) { if(m_config.id_interval () >0) {
int nmin=(m_sec0-m_secID)/60; int nmin=(m_sec0-m_secID)/60;
@ -3743,7 +3738,7 @@ void MainWindow::guiUpdate()
} }
if(m_mode=="FT8" or m_mode=="MSK144") { if(m_mode=="FT8" or m_mode=="MSK144") {
if(ui->txrb1->isEnabled() and m_nContest!=NONE and m_nContest!=EU_VHF) { if(ui->txrb1->isEnabled() and (m_nContest==NA_VHF or m_nContest==FIELD_DAY or m_nContest==RTTY)) {
//We're in a contest-like mode other than EU_VHF: start QSO with Tx2. //We're in a contest-like mode other than EU_VHF: start QSO with Tx2.
ui->tx1->setEnabled(false); ui->tx1->setEnabled(false);
} }
@ -3755,8 +3750,8 @@ void MainWindow::guiUpdate()
//Once per second: //Once per second:
if(nsec != m_sec0) { if(nsec != m_sec0) {
// qDebug() << "OneSec:" << m_nContest; // qDebug() << "OneSec:" << m_nContest << m_Nslots;
if(!m_msgAvgWidget and m_nContest>0 and m_nContest<6) on_actionFox_Log_triggered();
if(m_freqNominal!=0 and m_freqNominal<50000000 and m_config.enable_VHF_features()) { if(m_freqNominal!=0 and m_freqNominal<50000000 and m_config.enable_VHF_features()) {
if(!m_bVHFwarned) vhfWarning(); if(!m_bVHFwarned) vhfWarning();
} else { } else {
@ -3764,21 +3759,7 @@ void MainWindow::guiUpdate()
} }
m_currentBand=m_config.bands()->find(m_freqNominal); m_currentBand=m_config.bands()->find(m_freqNominal);
// if(m_config.bFox()) {
// if(m_config.my_callsign()=="K1JT" or m_config.my_callsign()=="K9AN" or
// m_config.my_callsign()=="G4WJS" or m_config.my_callsign().contains("KH7Z")) {
// ui->sbNslots->setMaximum(5);
// m_Nslots=ui->sbNslots->value();
// ui->sbNslots->setEnabled(true);
// } else {
// ui->sbNslots->setMaximum(1);
// m_Nslots=1;
// ui->sbNslots->setEnabled(false);
// }
// }
if(m_config.bHound()) { if(m_config.bHound()) {
// m_bWarnedHound=false;
qint32 tHound=QDateTime::currentMSecsSinceEpoch()/1000 - m_tAutoOn; qint32 tHound=QDateTime::currentMSecsSinceEpoch()/1000 - m_tAutoOn;
//To keep calling Fox, Hound must reactivate Enable Tx at least once every 2 minutes //To keep calling Fox, Hound must reactivate Enable Tx at least once every 2 minutes
if(tHound >= 120 and m_ntx==1) auto_tx_mode(false); if(tHound >= 120 and m_ntx==1) auto_tx_mode(false);
@ -3862,6 +3843,22 @@ void MainWindow::guiUpdate()
m_btxok0=m_btxok; m_btxok0=m_btxok;
} //End of guiUpdate } //End of guiUpdate
void MainWindow::useNextCall()
{
ui->dxCallEntry->setText(m_nextCall);
m_nextCall="";
ui->labNextCall->setStyleSheet("");
ui->labNextCall->setText("");
if(m_nextGrid.contains(grid_regexp)) {
ui->dxGridEntry->setText(m_nextGrid);
m_ntx=2;
ui->txrb2->setChecked(true);
} else {
m_ntx=3;
ui->txrb3->setChecked(true);
}
genStdMsgs(m_nextRpt);
}
void MainWindow::startTx2() void MainWindow::startTx2()
{ {
@ -4220,6 +4217,14 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
QString hiscall; QString hiscall;
QString hisgrid; QString hisgrid;
message.deCallAndGrid(/*out*/hiscall,hisgrid); message.deCallAndGrid(/*out*/hiscall,hisgrid);
if(message.string().contains(hiscall+"/R")) {
hiscall+="/R";
ui->dxCallEntry->setText(hiscall);
}
if(message.string().contains(hiscall+"/P")) {
hiscall+="/P";
ui->dxCallEntry->setText(hiscall);
}
bool is_73 = message_words.filter (QRegularExpression {"^(73|RR73)$"}).size (); bool is_73 = message_words.filter (QRegularExpression {"^(73|RR73)$"}).size ();
if (!is_73 and !message.isStandardMessage() and !message.string().contains("<")) { if (!is_73 and !message.isStandardMessage() and !message.string().contains("<")) {
@ -4266,7 +4271,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
} }
// prior DX call (possible QSO partner) // prior DX call (possible QSO partner)
auto qso_partner_base_call = Radio::base_callsign (ui->dxCallEntry-> text ()); auto qso_partner_base_call = Radio::base_callsign (ui->dxCallEntry->text ());
auto base_call = Radio::base_callsign (hiscall); auto base_call = Radio::base_callsign (hiscall);
// Determine appropriate response to received message // Determine appropriate response to received message
@ -4279,7 +4284,8 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
|| dtext.contains ("/" + m_baseCall + " ") || dtext.contains ("/" + m_baseCall + " ")
|| dtext.contains (" " + m_baseCall + "/") || dtext.contains (" " + m_baseCall + "/")
|| (firstcall == "DE")) { || (firstcall == "DE")) {
QString w2=message_words.at(2); QString w2="";
if(message_words.size()>=3) w2=message_words.at(2);
QString w34=""; QString w34="";
if(message_words.size()>=4) w34=message_words.at(3); if(message_words.size()>=4) w34=message_words.at(3);
int nrpt=w2.toInt(); int nrpt=w2.toInt();
@ -4367,10 +4373,21 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
gen_msg = 5; gen_msg = 5;
if (ui->rbGenMsg->isChecked ()) m_ntx=7; if (ui->rbGenMsg->isChecked ()) m_ntx=7;
m_gen_message_is_cq = false; m_gen_message_is_cq = false;
} else {
m_bTUmsg=false;
if(m_nContest==RTTY and m_nextCall!="") {
// We're in RTTY contest and have "nextCall" queued up: send a "TU; ..." message
on_logQSOButton_clicked();
ui->tx3->setText(ui->tx3->text().remove("TU; "));
useNextCall();
QString t="TU; " + ui->tx3->text();
ui->tx3->setText(t);
m_bTUmsg=true;
} else { } else {
m_ntx=5; m_ntx=5;
ui->txrb5->setChecked(true); ui->txrb5->setChecked(true);
} }
}
m_QSOProgress = SIGNOFF; m_QSOProgress = SIGNOFF;
} else if((m_QSOProgress >= REPORT } else if((m_QSOProgress >= REPORT
|| (m_QSOProgress >= REPLYING && (m_mode=="MSK144" or m_mode=="FT8"))) || (m_QSOProgress >= REPLYING && (m_mode=="MSK144" or m_mode=="FT8")))
@ -4402,7 +4419,8 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
} }
} }
else if (m_QSOProgress >= ROGERS else if (m_QSOProgress >= ROGERS
&& message_words.size () > 2 && message_words.at (1).contains (m_baseCall) && message_words.at (2) == "73") { && message_words.size () > 2 && message_words.at (1).contains (m_baseCall)
&& message_words.at (2) == "73") {
// 73 back to compound call holder // 73 back to compound call holder
if(ui->tabWidget->currentIndex()==1) { if(ui->tabWidget->currentIndex()==1) {
gen_msg = 5; gen_msg = 5;
@ -4416,7 +4434,8 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
m_QSOProgress = SIGNOFF; m_QSOProgress = SIGNOFF;
} }
else if (!(m_bAutoReply && m_QSOProgress > CALLING)) { else if (!(m_bAutoReply && m_QSOProgress > CALLING)) {
if ((message_words.size () > 4 && message_words.at (1).contains (m_baseCall) && message_words.at (4) == "OOO")) { if ((message_words.size () > 4 && message_words.at (1).contains (m_baseCall)
&& message_words.at (4) == "OOO")) {
// EME short code report or MSK144/FT8 contest mode reply, send back Tx3 // EME short code report or MSK144/FT8 contest mode reply, send back Tx3
m_ntx=3; m_ntx=3;
m_QSOProgress = ROGER_REPORT; m_QSOProgress = ROGER_REPORT;
@ -4447,6 +4466,17 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
} }
} }
else { // nothing for us else { // nothing for us
if(message_words.size () > 3 // enough fields for a normal message
&& m_nContest==RTTY
&& (message_words.at(1).contains(m_baseCall) || "DE" == message_words.at(1))
&& (!message_words.at(2).contains(qso_partner_base_call) and !bEU_VHF_w2)) {
// Queue up the next QSO partner
m_nextCall=message_words.at(2);
m_nextGrid=message_words.at(3);
m_nextRpt=message.report();
ui->labNextCall->setText("Next: " + m_nextCall);
ui->labNextCall->setStyleSheet("QLabel {background-color: #66ff66}");
}
return; return;
} }
} }
@ -4490,7 +4520,8 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
ui->txrb5->setChecked(true); ui->txrb5->setChecked(true);
} }
m_QSOProgress = SIGNOFF; m_QSOProgress = SIGNOFF;
} else {// just work them } else {
// just work them
if (ui->tx1->isEnabled ()) { if (ui->tx1->isEnabled ()) {
m_ntx = 1; m_ntx = 1;
m_QSOProgress = REPLYING; m_QSOProgress = REPLYING;
@ -4556,7 +4587,8 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
} }
ui->rptSpinBox->setValue(n); ui->rptSpinBox->setValue(n);
if (!m_nTx73) { // Don't genStdMsgs if we're already sending 73. // Don't genStdMsgs if we're already sending 73, or a "TU; " msg is queued.
if (!m_nTx73 and !m_bTUmsg) {
genStdMsgs(rpt); genStdMsgs(rpt);
if (gen_msg) { if (gen_msg) {
switch (gen_msg) { switch (gen_msg) {
@ -4628,10 +4660,12 @@ void MainWindow::genCQMsg ()
QString t=ui->tx6->text(); QString t=ui->tx6->text();
if((m_mode=="FT8" or m_mode=="MSK144") and m_nContest!=NONE and if((m_mode=="FT8" or m_mode=="MSK144") and m_nContest!=NONE and
t.split(" ").at(1)==m_config.my_callsign()) { t.split(" ").at(1)==m_config.my_callsign() and stdCall(m_config.my_callsign())) {
// if(m_nContest==NA_VHF) t="CQ QP" + t.mid(2,-1); if(m_nContest==NA_VHF) t="CQ TEST" + t.mid(2,-1);
if(m_nContest==EU_VHF) t="CQ TEST" + t.mid(2,-1);
if(m_nContest==FIELD_DAY) t="CQ FD" + t.mid(2,-1); if(m_nContest==FIELD_DAY) t="CQ FD" + t.mid(2,-1);
if(m_nContest==RTTY) t="CQ RU" + t.mid(2,-1); if(m_nContest==RTTY) t="CQ RU" + t.mid(2,-1);
if(m_nContest==FOX) t="CQ HUND" + t.mid(2,-1);
ui->tx6->setText(t); ui->tx6->setText(t);
} }
} else { } else {
@ -4666,6 +4700,10 @@ bool MainWindow::stdCall(QString w)
void MainWindow::genStdMsgs(QString rpt, bool unconditional) void MainWindow::genStdMsgs(QString rpt, bool unconditional)
{ {
if(ui->tx3->text().left(4)=="TU; ") {
return;
}
genCQMsg (); genCQMsg ();
auto const& hisCall=ui->dxCallEntry->text(); auto const& hisCall=ui->dxCallEntry->text();
if(!hisCall.size ()) { if(!hisCall.size ()) {
@ -4692,9 +4730,9 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
bool bHisCall=stdCall(hisCall); bool bHisCall=stdCall(hisCall);
bool b77=(m_mode=="MSK144" or m_mode=="FT8") and bool b77=(m_mode=="MSK144" or m_mode=="FT8") and
(!bMyCall or !bHisCall or m_config.bGenerate77()); (!bMyCall or !bHisCall or m_config.bGenerate77());
// qDebug() << "aa" << my_callsign << hisCall << bMyCall << bHisCall << b77;
QString t0=hisBase + " " + m_baseCall + " "; QString t0=hisBase + " " + m_baseCall + " ";
QString t0s=hisCall + " " + my_callsign + " ";
QString t0a,t0b; QString t0a,t0b;
if(b77) { if(b77) {
if(bHisCall and bMyCall) t0=hisCall + " " + my_callsign + " "; if(bHisCall and bMyCall) t0=hisCall + " " + my_callsign + " ";
@ -4704,7 +4742,8 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
QString t00=t0; QString t00=t0;
QString t {t0 + my_grid}; QString t {t0 + my_grid};
if(b77 and (!bMyCall or !bHisCall)) t=t0a; // if(b77 and (!bMyCall or !bHisCall)) t=t0a;
if(b77 and (!bMyCall)) t=t0a;
msgtype(t, ui->tx1); msgtype(t, ui->tx1);
if (eme_short_codes) { if (eme_short_codes) {
t=t+" OOO"; t=t+" OOO";
@ -4750,8 +4789,8 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
} }
if(m_mode=="MSK144" and m_bShMsgs) { if(m_mode=="MSK144" and m_bShMsgs) {
int i=t0.length()-1; int i=t0s.length()-1;
t0="<" + t0.mid(0,i) + "> "; t0="<" + t0s.mid(0,i) + "> ";
if(!m_config.bNA_VHF_Contest()) { if(!m_config.bNA_VHF_Contest()) {
if(n<=-2) n=-3; if(n<=-2) n=-3;
if(n>=-1 and n<=1) n=0; if(n>=-1 and n<=1) n=0;
@ -4770,14 +4809,14 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
t=t0 + "R" + rpt; t=t0 + "R" + rpt;
msgtype(t, ui->tx3); msgtype(t, ui->tx3);
} }
if(m_mode=="MSK144" and m_bShMsgs) { if(m_mode=="MSK144" and m_bShMsgs and m_nContest==NONE) {
t=t0 + "R" + rpt; t=t0 + "R" + rpt;
msgtype(t, ui->tx3); msgtype(t, ui->tx3);
m_send_RR73=false; m_send_RR73=false;
} }
t=t0 + (m_send_RR73 ? "RR73" : "RRR"); t=t0 + (m_send_RR73 ? "RR73" : "RRR");
if(m_mode=="MSK144" or m_mode=="FT8") { if((m_mode=="MSK144" and !m_bShMsgs) or m_mode=="FT8") {
if(!bHisCall and bMyCall) t=hisCall + " <" + my_callsign + "> " + (m_send_RR73 ? "RR73" : "RRR"); if(!bHisCall and bMyCall) t=hisCall + " <" + my_callsign + "> " + (m_send_RR73 ? "RR73" : "RRR");
if(bHisCall and !bMyCall) t="<" + hisCall + "> " + my_callsign + " " + (m_send_RR73 ? "RR73" : "RRR"); if(bHisCall and !bMyCall) t="<" + hisCall + "> " + my_callsign + " " + (m_send_RR73 ? "RR73" : "RRR");
} }
@ -4785,7 +4824,7 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
msgtype(t, ui->tx4); msgtype(t, ui->tx4);
t=t0 + "73"; t=t0 + "73";
if(m_mode=="MSK144" or m_mode=="FT8") { if((m_mode=="MSK144" and !m_bShMsgs) or m_mode=="FT8") {
if(!bHisCall and bMyCall) t=hisCall + " <" + my_callsign + "> 73"; if(!bHisCall and bMyCall) t=hisCall + " <" + my_callsign + "> 73";
if(bHisCall and !bMyCall) t="<" + hisCall + "> " + my_callsign + " 73"; if(bHisCall and !bMyCall) t="<" + hisCall + "> " + my_callsign + " 73";
} }
@ -4801,7 +4840,7 @@ void MainWindow::genStdMsgs(QString rpt, bool unconditional)
} }
} }
if(m_config.bGenerate77()) return; if(m_config.bGenerate77() or "MSK144" == m_mode) return;
if (is_compound) { if (is_compound) {
if (is_type_one) { if (is_type_one) {
@ -5194,6 +5233,9 @@ void MainWindow::on_logQSOButton_clicked() //Log QSO button
if(m_nContest==EU_VHF) { if(m_nContest==EU_VHF) {
m_rptSent=m_xSent.split(" ").at(0).left(2); m_rptSent=m_xSent.split(" ").at(0).left(2);
m_rptRcvd=m_xRcvd.split(" ").at(0).left(2); m_rptRcvd=m_xRcvd.split(" ").at(0).left(2);
m_hisGrid=m_xRcvd.split(" ").at(1);
grid=m_hisGrid;
ui->dxGridEntry->setText(grid);
} }
if(m_nContest==FIELD_DAY) { if(m_nContest==FIELD_DAY) {
m_rptSent=m_xSent.split(" ").at(0); m_rptSent=m_xSent.split(" ").at(0);
@ -5224,7 +5266,7 @@ void MainWindow::cabLog()
int nfreq=m_freqNominal/1000; int nfreq=m_freqNominal/1000;
if(m_freqNominal>50000000) nfreq=m_freqNominal/1000000; if(m_freqNominal>50000000) nfreq=m_freqNominal/1000000;
QString t; QString t;
t.sprintf("QSO: %5d RY ",nfreq); t.sprintf("QSO: %5d DG ",nfreq);
t=t + QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd hhmm ") + t=t + QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd hhmm ") +
m_config.my_callsign().leftJustified(13,' ') + m_xSent.leftJustified(14,' ') + m_config.my_callsign().leftJustified(13,' ') + m_xSent.leftJustified(14,' ') +
m_hisCall.leftJustified(13,' ') + m_xRcvd; m_hisCall.leftJustified(13,' ') + m_xRcvd;
@ -5238,6 +5280,8 @@ void MainWindow::cabLog()
m_hisCall.leftJustified(13,' ') + m_xSent.leftJustified(14,' ') + m_xRcvd; m_hisCall.leftJustified(13,' ') + m_xSent.leftJustified(14,' ') + m_xRcvd;
m_msgAvgWidget->contestAddLog(m_nContest,t); m_msgAvgWidget->contestAddLog(m_nContest,t);
} }
m_xSent="";
m_xRcvd="";
} else { } else {
MessageBox::warning_message (this, tr("File Open Error"), MessageBox::warning_message (this, tr("File Open Error"),
tr("Cannot open \"%1\" for append: %2").arg(f.fileName()).arg(f.errorString())); tr("Cannot open \"%1\" for append: %2").arg(f.fileName()).arg(f.errorString()));
@ -5315,7 +5359,7 @@ void MainWindow::displayWidgets(qint64 n)
if(i==25) ui->actionEnable_AP_JT65->setVisible (b); if(i==25) ui->actionEnable_AP_JT65->setVisible (b);
if(i==26) ui->actionEnable_AP_DXcall->setVisible (b); if(i==26) ui->actionEnable_AP_DXcall->setVisible (b);
if(i==27) ui->cbFirst->setVisible(b); if(i==27) ui->cbFirst->setVisible(b);
// if(i==28) ui->cbVHFcontest->setVisible(b); if(i==28) ui->labNextCall->setVisible(b);
if(i==29) ui->measure_check_box->setVisible(b); if(i==29) ui->measure_check_box->setVisible(b);
if(i==30) ui->labDXped->setVisible(b); if(i==30) ui->labDXped->setVisible(b);
if(i==31) ui->cbRxAll->setVisible(b); if(i==31) ui->cbRxAll->setVisible(b);
@ -5364,7 +5408,7 @@ void MainWindow::on_actionFT8_triggered()
ui->label_6->setText("Band Activity"); ui->label_6->setText("Band Activity");
ui->decodedTextLabel->setText( " UTC dB DT Freq Message"); ui->decodedTextLabel->setText( " UTC dB DT Freq Message");
} }
displayWidgets(nWidgets("111010000100111000010000100100001")); displayWidgets(nWidgets("111010000100111000010000100110001"));
ui->txrb2->setEnabled(true); ui->txrb2->setEnabled(true);
ui->txrb4->setEnabled(true); ui->txrb4->setEnabled(true);
ui->txrb5->setEnabled(true); ui->txrb5->setEnabled(true);
@ -5383,7 +5427,7 @@ void MainWindow::on_actionFT8_triggered()
ui->tabWidget->setCurrentIndex(2); ui->tabWidget->setCurrentIndex(2);
ui->TxFreqSpinBox->setValue(300); ui->TxFreqSpinBox->setValue(300);
displayWidgets(nWidgets("111010000100111000010000000000100")); displayWidgets(nWidgets("111010000100111000010000000000100"));
ui->labDXped->setText("DXpedition: Fox"); ui->labDXped->setText("Fox");
on_actionFox_Log_triggered(); on_actionFox_Log_triggered();
} }
if(m_config.bHound()) { if(m_config.bHound()) {
@ -5393,7 +5437,7 @@ void MainWindow::on_actionFT8_triggered()
ui->tabWidget->setCurrentIndex(0); ui->tabWidget->setCurrentIndex(0);
ui->cbHoldTxFreq->setChecked(true); ui->cbHoldTxFreq->setChecked(true);
displayWidgets(nWidgets("111010000100110000010000000000110")); displayWidgets(nWidgets("111010000100110000010000000000110"));
ui->labDXped->setText("DXpedition: Hound"); ui->labDXped->setText("Hound");
ui->txrb1->setChecked(true); ui->txrb1->setChecked(true);
ui->txrb2->setEnabled(false); ui->txrb2->setEnabled(false);
ui->txrb4->setEnabled(false); ui->txrb4->setEnabled(false);
@ -5995,8 +6039,9 @@ void MainWindow::on_actionExport_Cabrillo_log_triggered()
if(!m_exportCabrillo) { if(!m_exportCabrillo) {
m_exportCabrillo.reset(new ExportCabrillo{m_settings}); m_exportCabrillo.reset(new ExportCabrillo{m_settings});
} }
bool ret=m_exportCabrillo->exec(); QString CabLog=m_config.writeable_data_dir ().absoluteFilePath ("cabrillo.log");
qDebug() << "aa" << ret; m_exportCabrillo->setFile(CabLog);
m_exportCabrillo->exec();
} }
@ -7638,13 +7683,9 @@ void MainWindow::write_transmit_entry (QString const& file_name)
{ {
auto const& message = tr ("Cannot open \"%1\" for append: %2") auto const& message = tr ("Cannot open \"%1\" for append: %2")
.arg (f.fileName ()).arg (f.errorString ()); .arg (f.fileName ()).arg (f.errorString ());
#if QT_VERSION >= 0x050400
QTimer::singleShot (0, [=] { // don't block guiUpdate QTimer::singleShot (0, [=] { // don't block guiUpdate
MessageBox::warning_message (this, tr ("Log File Error"), message); MessageBox::warning_message (this, tr ("Log File Error"), message);
}); });
#else
MessageBox::warning_message (this, tr ("Log File Error"), message);
#endif
} }
} }
@ -7833,7 +7874,7 @@ void MainWindow::selectHound(QString line)
if(rpt.mid(0,1) != "-" and rpt.mid(0,1) != "+") t2="+" + rpt; if(rpt.mid(0,1) != "-" and rpt.mid(0,1) != "+") t2="+" + rpt;
if(t2.length()==2) t2=t2.mid(0,1) + "0" + t2.mid(1,1); if(t2.length()==2) t2=t2.mid(0,1) + "0" + t2.mid(1,1);
t1=t1.mid(0,12) + t2; t1=t1.mid(0,12) + t2;
ui->textBrowser4->displayFoxToBeCalled(t1,"#ffffff"); // Add hound call and rpt to tb4 ui->textBrowser4->displayFoxToBeCalled(t1); // Add hound call and rpt to tb4
t1=t1 + " " + houndGrid; // Append the grid t1=t1 + " " + houndGrid; // Append the grid
m_houndQueue.enqueue(t1); // Put this hound into the queue m_houndQueue.enqueue(t1); // Put this hound into the queue
writeFoxQSO(" Sel: " + t1); writeFoxQSO(" Sel: " + t1);

View File

@ -36,7 +36,7 @@
#include "astro.h" #include "astro.h"
#include "MessageBox.hpp" #include "MessageBox.hpp"
#include "NetworkAccessManager.hpp" #include "NetworkAccessManager.hpp"
#include "exportCabrillo.h" #include "ExportCabrillo.h"
#define NUM_JT4_SYMBOLS 206 //(72+31)*2, embedded sync #define NUM_JT4_SYMBOLS 206 //(72+31)*2, embedded sync
#define NUM_JT65_SYMBOLS 126 //63 data + 63 sync #define NUM_JT65_SYMBOLS 126 //63 data + 63 sync
@ -140,6 +140,7 @@ private slots:
void on_stopButton_clicked(); void on_stopButton_clicked();
void on_actionRelease_Notes_triggered (); void on_actionRelease_Notes_triggered ();
void on_actionFT8_DXpedition_Mode_User_Guide_triggered(); void on_actionFT8_DXpedition_Mode_User_Guide_triggered();
void on_actionQuick_Start_Guide_v2_triggered();
void on_actionOnline_User_Guide_triggered(); void on_actionOnline_User_Guide_triggered();
void on_actionLocal_User_Guide_triggered(); void on_actionLocal_User_Guide_triggered();
void on_actionWide_Waterfall_triggered(); void on_actionWide_Waterfall_triggered();
@ -343,7 +344,6 @@ private:
QSettings * m_settings; QSettings * m_settings;
QScopedPointer<Ui::MainWindow> ui; QScopedPointer<Ui::MainWindow> ui;
// other windows
Configuration m_config; Configuration m_config;
WSPRBandHopping m_WSPR_band_hopping; WSPRBandHopping m_WSPR_band_hopping;
bool m_WSPR_tx_next; bool m_WSPR_tx_next;
@ -504,6 +504,7 @@ private:
bool m_bAutoReply; bool m_bAutoReply;
bool m_bCheckedContest; bool m_bCheckedContest;
bool m_bWarnedSplit=false; bool m_bWarnedSplit=false;
bool m_bTUmsg;
enum enum
{ {
@ -587,6 +588,7 @@ private:
QString m_modeTx; QString m_modeTx;
QString m_fnameWE; // save path without extension QString m_fnameWE; // save path without extension
QString m_rpt; QString m_rpt;
QString m_nextRpt;
QString m_rptSent; QString m_rptSent;
QString m_rptRcvd; QString m_rptRcvd;
QString m_qsoStart; QString m_qsoStart;
@ -604,6 +606,8 @@ private:
QString m_xSent; //Contest exchange sent QString m_xSent; //Contest exchange sent
QString m_xRcvd; //Contest exchange received QString m_xRcvd; //Contest exchange received
QString m_currentBand; QString m_currentBand;
QString m_nextCall;
QString m_nextGrid;
QSet<QString> m_pfx; QSet<QString> m_pfx;
QSet<QString> m_sfx; QSet<QString> m_sfx;
@ -699,6 +703,7 @@ private:
void fast_config(bool b); void fast_config(bool b);
void CQTxFreq(); void CQTxFreq();
void cabLog(); void cabLog();
void useNextCall();
bool isWorked(int itype, QString key, float fMHz=0, QString=""); bool isWorked(int itype, QString key, float fMHz=0, QString="");
QString save_wave_file (QString const& name QString save_wave_file (QString const& name

View File

@ -654,6 +654,12 @@ QLabel[oob=&quot;true&quot;] {
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>50</width> <width>50</width>
@ -698,6 +704,12 @@ QLabel[oob=&quot;true&quot;] {
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="minimumSize">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>50</width> <width>50</width>
@ -1034,6 +1046,19 @@ QLabel[oob=&quot;true&quot;] {
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1">
<widget class="QLabel" name="labNextCall">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Double-click on another caller to queue that call for your next QSO.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Next Call</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -2621,11 +2646,11 @@ QPushButton[state=&quot;ok&quot;] {
<addaction name="actionErase_FoxQSO_txt"/> <addaction name="actionErase_FoxQSO_txt"/>
<addaction name="actionErase_wsjtx_log_adi"/> <addaction name="actionErase_wsjtx_log_adi"/>
<addaction name="actionErase_cabrillo_log"/> <addaction name="actionErase_cabrillo_log"/>
<addaction name="actionExport_Cabrillo_log"/>
<addaction name="actionOpen_log_directory"/> <addaction name="actionOpen_log_directory"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionSettings"/> <addaction name="actionSettings"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionExport_Cabrillo_log"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionExit"/> <addaction name="actionExit"/>
</widget> </widget>
@ -2672,6 +2697,7 @@ QPushButton[state=&quot;ok&quot;] {
<addaction name="actionOnline_User_Guide"/> <addaction name="actionOnline_User_Guide"/>
<addaction name="actionLocal_User_Guide"/> <addaction name="actionLocal_User_Guide"/>
<addaction name="actionFT8_DXpedition_Mode_User_Guide"/> <addaction name="actionFT8_DXpedition_Mode_User_Guide"/>
<addaction name="actionQuick_Start_Guide_v2"/>
<addaction name="download_samples_action"/> <addaction name="download_samples_action"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionKeyboard_shortcuts"/> <addaction name="actionKeyboard_shortcuts"/>
@ -3316,6 +3342,11 @@ QPushButton[state=&quot;ok&quot;] {
<string>Export Cabrillo log</string> <string>Export Cabrillo log</string>
</property> </property>
</action> </action>
<action name="actionQuick_Start_Guide_v2">
<property name="text">
<string>Quick-Start Guide to WSJT-X 2.0</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<customwidgets> <customwidgets>

View File

@ -18,7 +18,7 @@
QDataStream& operator << (QDataStream& os, CLASS::ENUM const& v) \ QDataStream& operator << (QDataStream& os, CLASS::ENUM const& v) \
{ \ { \
auto const& mo = CLASS::staticMetaObject; \ auto const& mo = CLASS::staticMetaObject; \
return os << mo.enumerator (mo.indexOfEnumerator (#ENUM)).valueToKey (v); \ return os << mo.enumerator (mo.indexOfEnumerator (#ENUM)).valueToKey (static_cast<int> (v)); \
} \ } \
\ \
QDataStream& operator >> (QDataStream& is, CLASS::ENUM& v) \ QDataStream& operator >> (QDataStream& is, CLASS::ENUM& v) \
@ -47,35 +47,9 @@
QString enum_to_qstring (CLASS::ENUM const& m) \ QString enum_to_qstring (CLASS::ENUM const& m) \
{ \ { \
auto const& mo = CLASS::staticMetaObject; \ auto const& mo = CLASS::staticMetaObject; \
return QString {mo.enumerator (mo.indexOfEnumerator (#ENUM)).valueToKey (m)}; \ return QString {mo.enumerator (mo.indexOfEnumerator (#ENUM)).valueToKey (static_cast<int> (m))}; \
} }
#if QT_VERSION >= 0x050500
// Qt 5.5 now has Q_ENUM which registers enumns better
#define ENUM_QDEBUG_OPS_DECL(CLASS, ENUM)
#define ENUM_QDEBUG_OPS_IMPL(CLASS, ENUM)
#else
#define Q_ENUM(E)
#include <QDebug>
class QVariant;
#define ENUM_QDEBUG_OPS_DECL(CLASS, ENUM) \
QDebug operator << (QDebug, CLASS::ENUM const&);
#define ENUM_QDEBUG_OPS_IMPL(CLASS, ENUM) \
QDebug operator << (QDebug d, CLASS::ENUM const& m) \
{ \
auto const& mo = CLASS::staticMetaObject; \
return d << mo.enumerator (mo.indexOfEnumerator (#ENUM)).valueToKey (m); \
}
#endif
inline inline
void throw_qstring (QString const& qs) void throw_qstring (QString const& qs)
{ {

View File

@ -1,4 +1,5 @@
<table cellspacing=1> <table cellspacing=1>
<tr><td><b>Esc </b></td><td>Stop transmitting</td></tr>
<tr><td><b>F1 </b></td><td>Online User's Guide</td></tr> <tr><td><b>F1 </b></td><td>Online User's Guide</td></tr>
<tr><td><b>Shift+F1 </b></td><td>Copyright Notice</td></tr> <tr><td><b>Shift+F1 </b></td><td>Copyright Notice</td></tr>
<tr><td><b>Ctrl+F1 </b></td><td>About WSJT-X</td></tr> <tr><td><b>Ctrl+F1 </b></td><td>About WSJT-X</td></tr>
@ -13,9 +14,11 @@
<tr><td><b>F11 </b></td><td>Move Rx frequency down 1 Hz</td></tr> <tr><td><b>F11 </b></td><td>Move Rx frequency down 1 Hz</td></tr>
<tr><td><b>Ctrl+F11 </b></td><td>Move identical Rx and Tx frequencies down 1 Hz</td></tr> <tr><td><b>Ctrl+F11 </b></td><td>Move identical Rx and Tx frequencies down 1 Hz</td></tr>
<tr><td><b>Shift+F11 </b></td><td>Move Tx frequency down 60 Hz</td></tr> <tr><td><b>Shift+F11 </b></td><td>Move Tx frequency down 60 Hz</td></tr>
<tr><td><b>Ctrl+Shift+F11 </b></td><td>Move dial frequency down 2000 Hz</td></tr>
<tr><td><b>F12 </b></td><td>Move Rx frequency up 1 Hz</td></tr> <tr><td><b>F12 </b></td><td>Move Rx frequency up 1 Hz</td></tr>
<tr><td><b>Ctrl+F12 </b></td><td>Move identical Rx and Tx frequencies up 1 Hz</td></tr> <tr><td><b>Ctrl+F12 </b></td><td>Move identical Rx and Tx frequencies up 1 Hz</td></tr>
<tr><td><b>Shift+F12 </b></td><td>Move Tx frequency up 60 Hz</td></tr> <tr><td><b>Shift+F12 </b></td><td>Move Tx frequency up 60 Hz</td></tr>
<tr><td><b>Ctrl+Shift+F12 </b></td><td>Move dial frequency up 2000 Hz</td></tr>
<tr><td><b>Alt+1-6 </b></td><td>Set now transmission to this number on Tab 1</td></tr> <tr><td><b>Alt+1-6 </b></td><td>Set now transmission to this number on Tab 1</td></tr>
<tr><td><b>Ctl+1-6 </b></td><td>Set next transmission to this number on Tab 1</td></tr> <tr><td><b>Ctl+1-6 </b></td><td>Set next transmission to this number on Tab 1</td></tr>
<tr><td><b>Alt+D </b></td><td>Decode again at QSO frequency</td></tr> <tr><td><b>Alt+D </b></td><td>Decode again at QSO frequency</td></tr>

View File

@ -68,7 +68,8 @@ SOURCES += \
WSPRBandHopping.cpp MessageAggregator.cpp SampleDownloader.cpp qt_helpers.cpp\ WSPRBandHopping.cpp MessageAggregator.cpp SampleDownloader.cpp qt_helpers.cpp\
MultiSettings.cpp PhaseEqualizationDialog.cpp IARURegions.cpp MessageBox.cpp \ MultiSettings.cpp PhaseEqualizationDialog.cpp IARURegions.cpp MessageBox.cpp \
EqualizationToolsDialog.cpp CallsignValidator.cpp ExchangeValidator.cpp \ EqualizationToolsDialog.cpp CallsignValidator.cpp ExchangeValidator.cpp \
colorhighlighting.cpp ExportCabrillo.cpp colorhighlighting.cpp ExportCabrillo.cpp LotWUsers.cpp DecodeHighlightingModel.cpp \
DecodeHighlightingListView.cpp
HEADERS += qt_helpers.hpp \ HEADERS += qt_helpers.hpp \
pimpl_h.hpp pimpl_impl.hpp \ pimpl_h.hpp pimpl_impl.hpp \
@ -85,7 +86,8 @@ HEADERS += qt_helpers.hpp \
messageaveraging.h echoplot.h echograph.h fastgraph.h fastplot.h Modes.hpp WSPRBandHopping.hpp \ messageaveraging.h echoplot.h echograph.h fastgraph.h fastplot.h Modes.hpp WSPRBandHopping.hpp \
WsprTxScheduler.h SampleDownloader.hpp MultiSettings.hpp PhaseEqualizationDialog.hpp \ WsprTxScheduler.h SampleDownloader.hpp MultiSettings.hpp PhaseEqualizationDialog.hpp \
IARURegions.hpp MessageBox.hpp EqualizationToolsDialog.hpp CallsignValidator.hpp \ IARURegions.hpp MessageBox.hpp EqualizationToolsDialog.hpp CallsignValidator.hpp \
ExchangeValidator.hpp colorhighlighting.h ExportCabrillo.h ExchangeValidator.hpp colorhighlighting.h ExportCabrillo.h LotWUsers.h \
DecodeHighlightingModel.hpp DecodeHighlightingListView.hpp
INCLUDEPATH += qmake_only INCLUDEPATH += qmake_only