Add proper Qt validation for callsigns and grids

Two      new     validator      classes     CallsignValidator      and
MaidenheadLocatorValidator   are   introduced    and   used   in   the
Configuration and MainWindow implementations.

MaidenheadLocatorValidator  supports  different  lengths  and  minimum
required  lengths  with  a  default of  subsquare  with  square  being
required.

The  message_aggregator  application has  been  enhanced  to show  the
current DX call and DX grid as shown in the WSJT-X main window.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@6903 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2016-07-10 22:20:30 +00:00
parent 039c9c023e
commit c586204d75
9 changed files with 214 additions and 119 deletions

View File

@ -234,6 +234,8 @@ set (wsjt_qt_CXXSRCS
SampleDownloader/RemoteFile.cpp SampleDownloader/RemoteFile.cpp
DisplayManual.cpp DisplayManual.cpp
MultiSettings.cpp MultiSettings.cpp
MaidenheadLocatorValidator.cpp
CallsignValidator.cpp
) )
set (wsjt_qtmm_CXXSRCS set (wsjt_qtmm_CXXSRCS

23
CallsignValidator.hpp Normal file
View File

@ -0,0 +1,23 @@
#ifndef CALLSIGN_VALIDATOR_HPP__
#define CALLSIGN_VALIDATOR_HPP__
#include <QValidator>
#include <QRegularExpression>
//
// CallsignValidator - QValidator implementation for callsigns
//
class CallsignValidator final
: public QValidator
{
public:
CallsignValidator (QObject * parent = nullptr, bool allow_compound = true);
// QValidator implementation
State validate (QString& input, int& pos) const override;
private:
QRegularExpression re_;
};
#endif

View File

@ -177,6 +177,8 @@
#include "StationList.hpp" #include "StationList.hpp"
#include "NetworkServerLookup.hpp" #include "NetworkServerLookup.hpp"
#include "MessageBox.hpp" #include "MessageBox.hpp"
#include "MaidenheadLocatorValidator.hpp"
#include "CallsignValidator.hpp"
#include "ui_Configuration.h" #include "ui_Configuration.h"
#include "moc_Configuration.cpp" #include "moc_Configuration.cpp"
@ -191,7 +193,6 @@ namespace
// QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"}; // QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"};
QRegExp message_alphabet {"[- @A-Za-z0-9+./?#<>]*"}; QRegExp message_alphabet {"[- @A-Za-z0-9+./?#<>]*"};
} }
@ -409,8 +410,6 @@ private:
Q_SLOT void on_add_macro_push_button_clicked (bool = false); Q_SLOT void on_add_macro_push_button_clicked (bool = false);
Q_SLOT void on_delete_macro_push_button_clicked (bool = false); Q_SLOT void on_delete_macro_push_button_clicked (bool = false);
Q_SLOT void on_PTT_method_button_group_buttonClicked (int); Q_SLOT void on_PTT_method_button_group_buttonClicked (int);
Q_SLOT void on_callsign_line_edit_editingFinished ();
Q_SLOT void on_grid_line_edit_editingFinished ();
Q_SLOT void on_add_macro_line_edit_editingFinished (); Q_SLOT void on_add_macro_line_edit_editingFinished ();
Q_SLOT void delete_macro (); Q_SLOT void delete_macro ();
void delete_selected_macros (QModelIndexList); void delete_selected_macros (QModelIndexList);
@ -870,8 +869,8 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
// //
// validation // validation
// //
ui_->callsign_line_edit->setValidator (new QRegExpValidator {QRegExp {"[A-Za-z0-9/]+"}, this}); ui_->callsign_line_edit->setValidator (new CallsignValidator {this});
ui_->grid_line_edit->setValidator (new QRegExpValidator {QRegExp {"[A-Ra-r]{2,2}[0-9]{2,2}[A-Xa-x]{0,2}"}, this}); ui_->grid_line_edit->setValidator (new MaidenheadLocatorValidator {this});
ui_->add_macro_line_edit->setValidator (new QRegExpValidator {message_alphabet, this}); ui_->add_macro_line_edit->setValidator (new QRegExpValidator {message_alphabet, this});
ui_->udp_server_port_spin_box->setMinimum (1); ui_->udp_server_port_spin_box->setMinimum (1);
@ -1135,8 +1134,8 @@ void Configuration::impl::read_settings ()
SettingsGroup g {settings_, "Configuration"}; SettingsGroup g {settings_, "Configuration"};
restoreGeometry (settings_->value ("window/geometry").toByteArray ()); restoreGeometry (settings_->value ("window/geometry").toByteArray ());
my_callsign_ = settings_->value ("MyCall", "").toString (); my_callsign_ = settings_->value ("MyCall", QString {}).toString ();
my_grid_ = settings_->value ("MyGrid", "").toString (); my_grid_ = settings_->value ("MyGrid", QString {}).toString ();
next_color_CQ_ = color_CQ_ = settings_->value("colorCQ","#66ff66").toString(); next_color_CQ_ = color_CQ_ = settings_->value("colorCQ","#66ff66").toString();
next_color_MyCall_ = color_MyCall_ = settings_->value("colorMyCall","#ff6666").toString(); next_color_MyCall_ = color_MyCall_ = settings_->value("colorMyCall","#ff6666").toString();
next_color_TxMsg_ = color_TxMsg_ = settings_->value("colorTxMsg","#ffff00").toString(); next_color_TxMsg_ = color_TxMsg_ = settings_->value("colorTxMsg","#ffff00").toString();
@ -2015,17 +2014,6 @@ void Configuration::impl::on_PTT_method_button_group_buttonClicked (int /* id */
set_rig_invariants (); set_rig_invariants ();
} }
void Configuration::impl::on_callsign_line_edit_editingFinished ()
{
ui_->callsign_line_edit->setText (ui_->callsign_line_edit->text ().toUpper ());
}
void Configuration::impl::on_grid_line_edit_editingFinished ()
{
auto text = ui_->grid_line_edit->text ();
ui_->grid_line_edit->setText (text.left (4).toUpper () + text.mid (4).toLower ());
}
void Configuration::impl::on_sound_input_combo_box_currentTextChanged (QString const& text) void Configuration::impl::on_sound_input_combo_box_currentTextChanged (QString const& text)
{ {
default_audio_input_device_selected_ = QAudioDeviceInfo::defaultInputDevice ().deviceName () == text; default_audio_input_device_selected_ = QAudioDeviceInfo::defaultInputDevice ().deviceName () == text;

View File

@ -0,0 +1,73 @@
#include "MaidenheadLocatorValidator.hpp"
MaidenheadLocatorValidator::MaidenheadLocatorValidator (QObject * parent, Length length, Length required)
: QValidator {parent}
{
switch (length)
{
case Length::field:
re_.setPattern ({R"(^(?<field>[A-Ra-r]{2})$)"});
break;
case Length::square:
if (Length::field == required)
{
re_.setPattern ({R"(^(?<field>[A-Ra-r]{2})([0-9]{2}){0,1}$)"});
}
else
{
re_.setPattern ({R"(^(?<field>[A-Ra-r]{2})[0-9]{2}$)"});
}
break;
case Length::subsquare:
if (Length::field == required)
{
re_.setPattern ({R"(^(?<field>[A-Ra-r]{2})([0-9]{2}((?<subsquare>[A-Xa-x]{2}){0,1})){0,1}$)"});
}
else if (Length::square == required)
{
re_.setPattern ({R"(^(?<field>[A-Ra-r]{2})[0-9]{2}(?<subsquare>[A-Xa-x]{2}){0,1}$)"});
}
else
{
re_.setPattern ({R"(^(?<field>[A-Ra-r]{2})[0-9]{2}(?<subsquare>[A-Xa-x]{2})$)"});
}
break;
case Length::extended:
if (Length::field == required)
{
re_.setPattern ({R"(^(?<field>[A-Ra-r]{2})([0-9]{2}((?<subsquare>[A-Xa-x]{2}){0,1}([0-9]{2}){0,1})){0,1}$)"});
}
else if (Length::square == required)
{
re_.setPattern ({R"(^(?<field>[A-Ra-r]{2})[0-9]{2}((?<subsquare>[A-Xa-x]{2})([0-9]{2}){0,1}){0,1}$)"});
}
else if (Length::subsquare == required)
{
re_.setPattern ({R"(^(?<field>[A-Ra-r]{2})[0-9]{2}(?<subsquare>[A-Xa-x]{2})([0-9]{2}){0,1}$)"});
}
else
{
re_.setPattern ({R"(^(?<field>[A-Ra-r]{2})[0-9]{2}(?<subsquare>[A-Xa-x]{2})[0-9]{2}$)"});
}
break;
}
}
auto MaidenheadLocatorValidator::validate (QString& input, int& pos) const -> State
{
auto match = re_.match (input, 0, QRegularExpression::PartialPreferCompleteMatch);
auto field = match.captured ("field");
if (field.size ())
{
input.replace (match.capturedStart ("field"), match.capturedLength ("field"), field.toUpper ());
}
auto subsquare = match.captured ("subsquare");
if (subsquare.size ())
{
input.replace (match.capturedStart ("subsquare"), match.capturedLength ("subsquare"), subsquare.toLower ());
}
if (match.hasMatch ()) return Acceptable;
if (!input.size () || match.hasPartialMatch ()) return Intermediate;
pos = input.size ();
return Invalid;
}

View File

@ -0,0 +1,26 @@
#ifndef MAIDENHEAD_LOCATOR_VALIDATOR_HPP__
#define MAIDENHEAD_LOCATOR_VALIDATOR_HPP__
#include <QValidator>
#include <QRegularExpression>
//
// MaidenheadLocatorValidator - QValidator implementation for grid locators
//
class MaidenheadLocatorValidator final
: public QValidator
{
public:
enum class Length {field = 2, square = 4, subsquare = 6, extended = 8};
MaidenheadLocatorValidator (QObject * parent = nullptr
, Length length = Length::subsquare
, Length required = Length::square);
// QValidator implementation
State validate (QString& input, int& pos) const override;
private:
QRegularExpression re_;
};
#endif

View File

@ -107,6 +107,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
, halt_tx_button_ {new QPushButton {tr ("&Halt Tx")}} , halt_tx_button_ {new QPushButton {tr ("&Halt Tx")}}
, mode_label_ {new QLabel} , mode_label_ {new QLabel}
, frequency_label_ {new QLabel} , frequency_label_ {new QLabel}
, dx_label_ {new QLabel}
, rx_df_label_ {new QLabel} , rx_df_label_ {new QLabel}
, tx_df_label_ {new QLabel} , tx_df_label_ {new QLabel}
, report_label_ {new QLabel} , report_label_ {new QLabel}
@ -170,6 +171,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
auto status_bar = new QStatusBar; auto status_bar = new QStatusBar;
status_bar->addPermanentWidget (mode_label_); status_bar->addPermanentWidget (mode_label_);
status_bar->addPermanentWidget (frequency_label_); status_bar->addPermanentWidget (frequency_label_);
status_bar->addPermanentWidget (dx_label_);
status_bar->addPermanentWidget (rx_df_label_); status_bar->addPermanentWidget (rx_df_label_);
status_bar->addPermanentWidget (tx_df_label_); status_bar->addPermanentWidget (tx_df_label_);
status_bar->addPermanentWidget (report_label_); status_bar->addPermanentWidget (report_label_);
@ -191,10 +193,10 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
}); });
} }
void ClientWidget::update_status (QString const& id, Frequency f, QString const& mode, QString const& /*dx_call*/ void ClientWidget::update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call
, QString const& report, QString const& tx_mode, bool tx_enabled , QString const& report, QString const& tx_mode, bool tx_enabled
, bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df , bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df
, QString const& de_call, QString const& /*de_grid*/, QString const& /*dx_grid*/ , QString const& de_call, QString const& /*de_grid*/, QString const& dx_grid
, bool watchdog_timeout) , bool watchdog_timeout)
{ {
if (id == id_) if (id == id_)
@ -205,6 +207,8 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const&
.arg (mode) .arg (mode)
.arg (tx_mode.isEmpty () || tx_mode == mode ? "" : '(' + tx_mode + ')')); .arg (tx_mode.isEmpty () || tx_mode == mode ? "" : '(' + tx_mode + ')'));
frequency_label_->setText ("QRG: " + Radio::pretty_frequency_MHz_string (f)); frequency_label_->setText ("QRG: " + Radio::pretty_frequency_MHz_string (f));
dx_label_->setText (dx_call.size () >= 0 ? QString {"DX: %1%2"}.arg (dx_call)
.arg (dx_grid.size () ? '(' + dx_grid + ')' : QString {}) : QString {});
rx_df_label_->setText (rx_df >= 0 ? QString {"Rx: %1"}.arg (rx_df) : ""); rx_df_label_->setText (rx_df >= 0 ? QString {"Rx: %1"}.arg (rx_df) : "");
tx_df_label_->setText (tx_df >= 0 ? QString {"Tx: %1"}.arg (tx_df) : ""); tx_df_label_->setText (tx_df >= 0 ? QString {"Tx: %1"}.arg (tx_df) : "");
report_label_->setText ("SNR: " + report); report_label_->setText ("SNR: " + report);

View File

@ -26,13 +26,14 @@ public:
Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call Q_SLOT void update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call
, QString const& report, QString const& tx_mode, bool tx_enabled , QString const& report, QString const& tx_mode, bool tx_enabled
, bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df , bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df
, QString const& de_call, QString const& de_grid, QString const& dx_grid, bool watchdog_timeout); , QString const& de_call, QString const& de_grid, QString const& dx_grid
Q_SLOT void decode_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/ , bool watchdog_timeout);
, float /*delta_time*/, quint32 /*delta_frequency*/, QString const& /*mode*/ Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime, qint32 snr
, QString const& /*message*/); , float delta_time, quint32 delta_frequency, QString const& mode
Q_SLOT void beacon_spot_added (bool /*is_new*/, QString const& client_id, QTime /*time*/, qint32 /*snr*/ , QString const& message);
, float /*delta_time*/, Frequency /*delta_frequency*/, qint32 /*drift*/ Q_SLOT void beacon_spot_added (bool is_new, QString const& client_id, QTime, qint32 snr
, QString const& /*callsign*/, QString const& /*grid*/, qint32 /*power*/); , float delta_time, Frequency delta_frequency, qint32 drift
, QString const& callsign, QString const& grid, qint32 power);
Q_SIGNAL void do_reply (QModelIndex const&); Q_SIGNAL void do_reply (QModelIndex const&);
Q_SIGNAL void do_halt_tx (QString const& id, bool auto_only); Q_SIGNAL void do_halt_tx (QString const& id, bool auto_only);
@ -68,6 +69,7 @@ private:
QAbstractButton * halt_tx_button_; QAbstractButton * halt_tx_button_;
QLabel * mode_label_; QLabel * mode_label_;
QLabel * frequency_label_; QLabel * frequency_label_;
QLabel * dx_label_;
QLabel * rx_df_label_; QLabel * rx_df_label_;
QLabel * tx_df_label_; QLabel * tx_df_label_;
QLabel * report_label_; QLabel * report_label_;

View File

@ -54,6 +54,8 @@
#include "SampleDownloader.hpp" #include "SampleDownloader.hpp"
#include "Audio/BWFFile.hpp" #include "Audio/BWFFile.hpp"
#include "MultiSettings.hpp" #include "MultiSettings.hpp"
#include "MaidenheadLocatorValidator.hpp"
#include "CallsignValidator.hpp"
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "moc_mainwindow.cpp" #include "moc_mainwindow.cpp"
@ -137,6 +139,7 @@ namespace
{ {
Radio::Frequency constexpr default_frequency {14076000}; Radio::Frequency constexpr default_frequency {14076000};
QRegExp message_alphabet {"[- @A-Za-z0-9+./?#<>]*"}; QRegExp message_alphabet {"[- @A-Za-z0-9+./?#<>]*"};
QRegExp grid_regexp {QRegExp {"[A-Ra-r]{2}[0-9]{2}([A-Xa-x]{2}){0,1}"}};
bool message_is_73 (int type, QStringList const& msg_parts) bool message_is_73 (int type, QStringList const& msg_parts)
{ {
@ -340,6 +343,8 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
{ {
ui->setupUi(this); ui->setupUi(this);
add_child_to_event_filter (this); add_child_to_event_filter (this);
ui->dxGridEntry->setValidator (new MaidenheadLocatorValidator {this});
ui->dxCallEntry->setValidator (new CallsignValidator {this});
m_baseCall = Radio::base_callsign (m_config.my_callsign ()); m_baseCall = Radio::base_callsign (m_config.my_callsign ());
@ -951,8 +956,8 @@ void MainWindow::readSettings()
m_settings->beginGroup("MainWindow"); m_settings->beginGroup("MainWindow");
restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ()); restoreGeometry (m_settings->value ("geometry", saveGeometry ()).toByteArray ());
restoreState (m_settings->value ("state", saveState ()).toByteArray ()); restoreState (m_settings->value ("state", saveState ()).toByteArray ());
ui->dxCallEntry->setText(m_settings->value("DXcall","").toString()); ui->dxCallEntry->setText (m_settings->value ("DXcall", QString {}).toString ());
ui->dxGridEntry->setText(m_settings->value("DXgrid","").toString()); ui->dxGridEntry->setText (m_settings->value ("DXgrid", QString {}).toString ());
m_path = m_settings->value("MRUdir", m_config.save_directory ().absolutePath ()).toString (); m_path = m_settings->value("MRUdir", m_config.save_directory ().absolutePath ()).toString ();
m_txFirst = m_settings->value("TxFirst",false).toBool(); m_txFirst = m_settings->value("TxFirst",false).toBool();
auto displayAstro = m_settings->value ("AstroDisplayed", false).toBool (); auto displayAstro = m_settings->value ("AstroDisplayed", false).toBool ();
@ -2149,10 +2154,10 @@ void MainWindow::decode() //decode()
strncpy(dec_data.params.datetime, m_dateTime.toLatin1(), 20); strncpy(dec_data.params.datetime, m_dateTime.toLatin1(), 20);
strncpy(dec_data.params.mycall, (m_config.my_callsign()+" ").toLatin1(),12); strncpy(dec_data.params.mycall, (m_config.my_callsign()+" ").toLatin1(),12);
strncpy(dec_data.params.mygrid, (m_config.my_grid()+" ").toLatin1(),6); strncpy(dec_data.params.mygrid, (m_config.my_grid()+" ").toLatin1(),6);
QString hisCall=ui->dxCallEntry->text().toUpper().trimmed(); QString hisCall {ui->dxCallEntry->text ()};
QString hisGrid=ui->dxGridEntry->text().toUpper().trimmed(); QString hisGrid {ui->dxGridEntry->text ()};
strncpy(dec_data.params.hiscall,(hisCall+" ").toLatin1(),12); strncpy(dec_data.params.hiscall,(hisCall + " ").toLatin1 ().constData (), 12);
strncpy(dec_data.params.hisgrid,(hisGrid+" ").toLatin1(),6); strncpy(dec_data.params.hisgrid,(hisGrid + " ").toLatin1 ().constData (), 6);
//newdat=1 ==> this is new data, must do the big FFT //newdat=1 ==> this is new data, must do the big FFT
//nagain=1 ==> decode only at fQSO +/- Tol //nagain=1 ==> decode only at fQSO +/- Tol
@ -2265,7 +2270,7 @@ void::MainWindow::fast_decode_done()
QString msg=message.mid(0,4) + message.mid(6,-1); QString msg=message.mid(0,4) + message.mid(6,-1);
decodedtext=msg.replace("\n",""); decodedtext=msg.replace("\n","");
bool stdMsg = decodedtext.report(m_baseCall, bool stdMsg = decodedtext.report(m_baseCall,
Radio::base_callsign(ui->dxCallEntry->text().toUpper().trimmed()), m_rptRcvd); Radio::base_callsign(ui->dxCallEntry->text()), m_rptRcvd);
// extract details and send to PSKreporter // extract details and send to PSKreporter
if(m_config.spot_to_psk_reporter() and stdMsg and !m_diskData) { if(m_config.spot_to_psk_reporter() and stdMsg and !m_diskData) {
@ -2277,7 +2282,7 @@ void::MainWindow::fast_decode_done()
int snr = decodedtext.snr(); int snr = decodedtext.snr();
Frequency frequency = m_freqNominal + audioFrequency; Frequency frequency = m_freqNominal + audioFrequency;
pskSetLocal(); pskSetLocal();
if(gridOK(grid)) if(grid_regexp.exactMatch (grid))
{ {
// qDebug() << "To PSKreporter:" << deCall << grid << frequency << msgmode << snr; // qDebug() << "To PSKreporter:" << deCall << grid << frequency << msgmode << snr;
psk_Reporter->addRemoteStation(deCall,grid,QString::number(frequency),msgmode, psk_Reporter->addRemoteStation(deCall,grid,QString::number(frequency),msgmode,
@ -2422,7 +2427,7 @@ void MainWindow::readFromStdout() //readFromStdout
// find and extract any report for myCall // find and extract any report for myCall
bool stdMsg = decodedtext.report(m_baseCall, bool stdMsg = decodedtext.report(m_baseCall,
Radio::base_callsign(ui->dxCallEntry->text().toUpper().trimmed()), m_rptRcvd); Radio::base_callsign(ui->dxCallEntry->text()), m_rptRcvd);
// extract details and send to PSKreporter // extract details and send to PSKreporter
int nsec=QDateTime::currentMSecsSinceEpoch()/1000-m_secBandChanged; int nsec=QDateTime::currentMSecsSinceEpoch()/1000-m_secBandChanged;
bool okToPost=(nsec>50); bool okToPost=(nsec>50);
@ -2436,7 +2441,7 @@ void MainWindow::readFromStdout() //readFromStdout
int snr = decodedtext.snr(); int snr = decodedtext.snr();
Frequency frequency = m_freqNominal + audioFrequency; Frequency frequency = m_freqNominal + audioFrequency;
pskSetLocal (); pskSetLocal ();
if(gridOK(grid)) if(grid_regexp.exactMatch (grid))
{ {
// qDebug() << "To PSKreporter:" << deCall << grid << frequency << msgmode << snr; // qDebug() << "To PSKreporter:" << deCall << grid << frequency << msgmode << snr;
psk_Reporter->addRemoteStation(deCall,grid,QString::number(frequency),msgmode, psk_Reporter->addRemoteStation(deCall,grid,QString::number(frequency),msgmode,
@ -3275,19 +3280,19 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl
} }
// prior DX call (possible QSO partner) // prior DX call (possible QSO partner)
auto qso_partner_base_call = Radio::base_callsign (ui->dxCallEntry-> text ().toUpper ().trimmed ()); 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);
if (base_call != Radio::base_callsign (ui->dxCallEntry-> text ().toUpper ().trimmed ()) || base_call != hiscall) if (base_call != Radio::base_callsign (ui->dxCallEntry-> text ()) || base_call != hiscall)
{ {
// his base call different or his call more qualified // his base call different or his call more qualified
// i.e. compound version of same base call // i.e. compound version of same base call
ui->dxCallEntry->setText(hiscall); ui->dxCallEntry->setText (hiscall);
} }
if (gridOK(hisgrid)) { if (grid_regexp.exactMatch (hisgrid)) {
if(ui->dxGridEntry->text().mid(0,4) != hisgrid) ui->dxGridEntry->setText(hisgrid); if(ui->dxGridEntry->text().mid(0,4) != hisgrid) ui->dxGridEntry->setText(hisgrid);
} }
if (ui->dxGridEntry->text()=="") if (!ui->dxGridEntry->text ().size ())
lookup(); lookup();
m_hisGrid = ui->dxGridEntry->text(); m_hisGrid = ui->dxGridEntry->text();
@ -3312,7 +3317,7 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl
{ {
if (t4.size () > 7 // enough fields for a normal msg if (t4.size () > 7 // enough fields for a normal msg
and !gridOK (t4.at (7))) // but no grid on end of msg and !grid_regexp.exactMatch (t4.at (7))) // but no grid on end of msg
{ {
QString r=t4.at (7); QString r=t4.at (7);
if(r.mid(0,3)=="RRR" || (r.toInt()==73)) { if(r.mid(0,3)=="RRR" || (r.toInt()==73)) {
@ -3403,7 +3408,7 @@ void MainWindow::processMessage(QString const& messages, int position, bool ctrl
if(m_config.quick_call()) auto_tx_mode(true); if(m_config.quick_call()) auto_tx_mode(true);
} }
void MainWindow::genStdMsgs(QString rpt) //genStdMsgs() void MainWindow::genStdMsgs(QString rpt)
{ {
QString t; QString t;
if(m_config.my_callsign() !="" and m_config.my_grid() !="") if(m_config.my_callsign() !="" and m_config.my_grid() !="")
@ -3420,17 +3425,16 @@ void MainWindow::genStdMsgs(QString rpt) //genStdMsgs()
{ {
ui->tx6->setText(""); ui->tx6->setText("");
} }
QString hisCall=ui->dxCallEntry->text().toUpper().trimmed(); QString hisCall=ui->dxCallEntry->text();
ui->dxCallEntry->setText(hisCall); if(!hisCall.size ()) {
if(hisCall=="") { ui->labAz->clear ();
ui->labAz->setText(""); ui->labDist->clear ();
ui->labDist->setText(""); ui->tx1->clear ();
ui->tx1->setText(""); ui->tx2->clear ();
ui->tx2->setText(""); ui->tx3->clear ();
ui->tx3->setText(""); ui->tx4->clear ();
ui->tx4->setText(""); ui->tx5->lineEdit ()->clear ();
ui->tx5->setCurrentText(""); ui->genMsg->clear ();
ui->genMsg->setText("");
return; return;
} }
QString hisBase = Radio::base_callsign (hisCall); QString hisBase = Radio::base_callsign (hisCall);
@ -3438,7 +3442,7 @@ void MainWindow::genStdMsgs(QString rpt) //genStdMsgs()
QString t0=hisBase + " " + m_baseCall + " "; QString t0=hisBase + " " + m_baseCall + " ";
t=t0 + m_config.my_grid ().mid(0,4); t=t0 + m_config.my_grid ().mid(0,4);
msgtype(t, ui->tx1); msgtype(t, ui->tx1);
if(rpt == "") { if(!rpt.size ()) {
t=t+" OOO"; t=t+" OOO";
msgtype(t, ui->tx2); msgtype(t, ui->tx2);
msgtype("RO", ui->tx3); msgtype("RO", ui->tx3);
@ -3536,15 +3540,13 @@ void MainWindow::TxAgain()
void MainWindow::clearDX () void MainWindow::clearDX ()
{ {
ui->dxCallEntry->setText(""); ui->dxCallEntry->clear ();
ui->dxGridEntry->setText(""); ui->dxGridEntry->clear ();
m_hisCall=""; m_rptSent.clear ();
m_hisGrid=""; m_rptRcvd.clear ();
m_rptSent=""; m_qsoStart.clear ();
m_rptRcvd=""; m_qsoStop.clear ();
m_qsoStart=""; genStdMsgs (QString {});
m_qsoStop="";
genStdMsgs("");
if (1 == ui->tabWidget->currentIndex()) if (1 == ui->tabWidget->currentIndex())
{ {
ui->genMsg->setText(ui->tx6->text()); ui->genMsg->setText(ui->tx6->text());
@ -3560,12 +3562,8 @@ void MainWindow::clearDX ()
void MainWindow::lookup() //lookup() void MainWindow::lookup() //lookup()
{ {
QString hisCall=ui->dxCallEntry->text().toUpper().trimmed(); QString hisCall {ui->dxCallEntry->text()};
if (hisCall.isEmpty ()) if (!hisCall.size ()) return;
{
return;
}
ui->dxCallEntry->setText(hisCall);
QFile f {m_dataDir.absoluteFilePath ("CALL3.TXT")}; QFile f {m_dataDir.absoluteFilePath ("CALL3.TXT")};
if (f.open (QIODevice::ReadOnly | QIODevice::Text)) if (f.open (QIODevice::ReadOnly | QIODevice::Text))
{ {
@ -3574,7 +3572,7 @@ void MainWindow::lookup() //lookup()
for(int i=0; i<999999; i++) { for(int i=0; i<999999; i++) {
n=f.readLine(c,sizeof(c)); n=f.readLine(c,sizeof(c));
if(n <= 0) { if(n <= 0) {
ui->dxGridEntry->setText(""); ui->dxGridEntry->clear ();
break; break;
} }
QString t=QString(c); QString t=QString(c);
@ -3602,14 +3600,14 @@ void MainWindow::on_lookupButton_clicked() //Lookup button
void MainWindow::on_addButton_clicked() //Add button void MainWindow::on_addButton_clicked() //Add button
{ {
if(ui->dxGridEntry->text()=="") { if(!ui->dxGridEntry->text ().size ()) {
MessageBox::warning_message (this, tr ("Add to CALL3.TXT") MessageBox::warning_message (this, tr ("Add to CALL3.TXT")
, tr ("Please enter a valid grid locator")); , tr ("Please enter a valid grid locator"));
return; return;
} }
m_call3Modified=false; m_call3Modified=false;
QString hisCall=ui->dxCallEntry->text().toUpper().trimmed(); QString hisCall=ui->dxCallEntry->text();
QString hisgrid=ui->dxGridEntry->text().trimmed(); QString hisgrid=ui->dxGridEntry->text();
QString newEntry=hisCall + "," + hisgrid; QString newEntry=hisCall + "," + hisgrid;
// int ret = MessageBox::query_message(this, tr ("Add to CALL3.TXT"), // int ret = MessageBox::query_message(this, tr ("Add to CALL3.TXT"),
@ -3763,29 +3761,20 @@ void MainWindow::on_tx6_editingFinished() //tx6 edited
msgtype(t, ui->tx6); msgtype(t, ui->tx6);
} }
void MainWindow::on_dxCallEntry_textChanged(const QString &t) //dxCall changed void MainWindow::on_dxCallEntry_textChanged (QString const& call)
{ {
m_hisCall=t.toUpper().trimmed(); m_hisCall = call;
ui->dxCallEntry->setText(m_hisCall);
statusChanged(); statusChanged();
statusUpdate (); statusUpdate ();
} }
void MainWindow::on_dxGridEntry_textChanged(const QString &t) //dxGrid changed void MainWindow::on_dxGridEntry_textChanged (QString const& grid)
{ {
int n=t.length(); if (ui->dxGridEntry->hasAcceptableInput ()) {
if(n!=4 and n!=6) { if (grid != m_hisGrid) {
ui->labAz->setText(""); m_hisGrid = grid;
ui->labDist->setText(""); statusUpdate ();
return; }
}
if(!t[0].isLetter() or !t[1].isLetter()) return;
if(!t[2].isDigit() or !t[3].isDigit()) return;
if(n==4) m_hisGrid=t.mid(0,2).toUpper() + t.mid(2,2);
if(n==6) m_hisGrid=t.mid(0,2).toUpper() + t.mid(2,2) +
t.mid(4,2).toLower();
ui->dxGridEntry->setText(m_hisGrid);
if(gridOK(m_hisGrid)) {
qint64 nsec = QDateTime::currentMSecsSinceEpoch() % 86400; qint64 nsec = QDateTime::currentMSecsSinceEpoch() % 86400;
double utch=nsec/3600.0; double utch=nsec/3600.0;
int nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter; int nAz,nEl,nDmiles,nDkm,nHotAz,nHotABetter;
@ -3794,7 +3783,7 @@ void MainWindow::on_dxGridEntry_textChanged(const QString &t) //dxGrid changed
&nAz,&nEl,&nDmiles,&nDkm,&nHotAz,&nHotABetter,6,6); &nAz,&nEl,&nDmiles,&nDkm,&nHotAz,&nHotABetter,6,6);
QString t; QString t;
t.sprintf("Az: %d",nAz); t.sprintf("Az: %d",nAz);
ui->labAz->setText(t); ui->labAz->setText (grid);
if (m_config.miles ()) if (m_config.miles ())
{ {
t.sprintf ("%d mi", int (0.621371 * nDkm)); t.sprintf ("%d mi", int (0.621371 * nDkm));
@ -3804,11 +3793,16 @@ void MainWindow::on_dxGridEntry_textChanged(const QString &t) //dxGrid changed
t.sprintf ("%d km", nDkm); t.sprintf ("%d km", nDkm);
} }
ui->labDist->setText(t); ui->labDist->setText(t);
} else {
ui->labAz->setText("");
ui->labDist->setText("");
} }
statusUpdate (); else {
if (m_hisGrid.size ())
{
m_hisGrid.clear ();
ui->labAz->clear ();
ui->labDist->clear ();
statusUpdate ();
}
}
} }
void MainWindow::on_genStdMsgsPushButton_clicked() //genStdMsgs button void MainWindow::on_genStdMsgsPushButton_clicked() //genStdMsgs button
@ -3818,7 +3812,7 @@ void MainWindow::on_genStdMsgsPushButton_clicked() //genStdMsgs button
void MainWindow::on_logQSOButton_clicked() //Log QSO button void MainWindow::on_logQSOButton_clicked() //Log QSO button
{ {
if(m_hisCall=="") return; if (!m_hisCall.size ()) return;
m_dateTimeQSO=QDateTime::currentDateTimeUtc(); m_dateTimeQSO=QDateTime::currentDateTimeUtc();
m_logDlg->initLogQSO (m_hisCall, m_hisGrid, m_modeTx, m_rptSent, m_rptRcvd, m_logDlg->initLogQSO (m_hisCall, m_hisGrid, m_modeTx, m_rptSent, m_rptRcvd,
@ -4371,22 +4365,6 @@ void MainWindow::on_actionOpen_log_directory_triggered ()
QDesktopServices::openUrl (QUrl::fromLocalFile (m_dataDir.absolutePath ())); QDesktopServices::openUrl (QUrl::fromLocalFile (m_dataDir.absolutePath ()));
} }
bool MainWindow::gridOK(QString g)
{
bool b=false;
if(g.length()>=4) {
b=g.mid(0,1).compare("A")>=0 and
g.mid(0,1).compare("R")<=0 and
g.mid(1,1).compare("A")>=0 and
g.mid(1,1).compare("R")<=0 and
g.mid(2,1).compare("0")>=0 and
g.mid(2,1).compare("9")<=0 and
g.mid(3,1).compare("0")>=0 and
g.mid(3,1).compare("9")<=0;
}
return b;
}
void MainWindow::on_bandComboBox_currentIndexChanged (int index) void MainWindow::on_bandComboBox_currentIndexChanged (int index)
{ {
auto const& frequencies = m_config.frequencies (); auto const& frequencies = m_config.frequencies ();

View File

@ -157,8 +157,8 @@ private slots:
void on_txb6_clicked(); void on_txb6_clicked();
void on_lookupButton_clicked(); void on_lookupButton_clicked();
void on_addButton_clicked(); void on_addButton_clicked();
void on_dxCallEntry_textChanged(const QString &arg1); void on_dxCallEntry_textChanged (QString const&);
void on_dxGridEntry_textChanged(const QString &arg1); void on_dxGridEntry_textChanged (QString const&);
void on_genStdMsgsPushButton_clicked(); void on_genStdMsgsPushButton_clicked();
void on_logQSOButton_clicked(); void on_logQSOButton_clicked();
void on_actionJT9_triggered(); void on_actionJT9_triggered();
@ -522,7 +522,6 @@ private:
void msgtype(QString t, QLineEdit* tx); void msgtype(QString t, QLineEdit* tx);
void stub(); void stub();
void statusChanged(); void statusChanged();
bool gridOK(QString g);
bool shortList(QString callsign); bool shortList(QString callsign);
void transmit (double snr = 99.); void transmit (double snr = 99.);
void rigFailure (QString const& reason); void rigFailure (QString const& reason);