From 50901a5354d5d060411c1b1749d91f5369f11847 Mon Sep 17 00:00:00 2001 From: Bill Somerville Date: Wed, 4 Mar 2015 12:22:33 +0000 Subject: [PATCH] Better handling of compound callsigns Option to control standard message generation for type 2 compound callsign holders. Process decoded messages based on either base or full callsign for both DE and DX callsigns. Change CW id when callsign changed in settings. Merged from wsjtx-1.4 branch. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@5000 ab8295b8-cf94-4d9e-aec4-7959e3be5d79 --- Configuration.cpp | 13 ++++++ Configuration.hpp | 8 +++- Configuration.ui | 79 +++++++++++++++++++++++++-------- decodedtext.cpp | 12 +++-- decodedtext.h | 2 +- displaytext.cpp | 6 ++- mainwindow.cpp | 110 ++++++++++++++++++++++++++++++++++------------ 7 files changed, 178 insertions(+), 52 deletions(-) diff --git a/Configuration.cpp b/Configuration.cpp index 64a26b62a..544856391 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -181,6 +181,8 @@ namespace { qRegisterMetaType ("Configuration::DataMode"); qRegisterMetaTypeStreamOperators ("Configuration::DataMode"); + qRegisterMetaType ("Configuration::Type2MsgGen"); + qRegisterMetaTypeStreamOperators ("Configuration::Type2MsgGen"); } } static_initializer; @@ -475,6 +477,8 @@ private: float jt9w_min_dt_; float jt9w_max_dt_; + Type2MsgGen type_2_msg_gen_; + QStringListModel macros_; RearrangableMacrosModel next_macros_; QAction * macro_delete_action_; @@ -587,6 +591,7 @@ bool Configuration::restart_audio_output () const {return m_->restart_sound_outp unsigned Configuration::jt9w_bw_mult () const {return m_->jt9w_bw_mult_;} float Configuration::jt9w_min_dt () const {return m_->jt9w_min_dt_;} float Configuration::jt9w_max_dt () const {return m_->jt9w_max_dt_;} +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_grid () const {return m_->my_grid_;} QColor Configuration::color_CQ () const {return m_->color_CQ_;} @@ -1025,6 +1030,7 @@ void Configuration::impl::initialise_models () ui_->jt9w_bandwidth_mult_combo_box->setCurrentText (QString::number (jt9w_bw_mult_)); ui_->jt9w_min_dt_double_spin_box->setValue (jt9w_min_dt_); ui_->jt9w_max_dt_double_spin_box->setValue (jt9w_max_dt_); + ui_->type_2_msg_gen_combo_box->setCurrentIndex (type_2_msg_gen_); ui_->rig_combo_box->setCurrentText (rig_params_.rig_name_); ui_->TX_mode_button_group->button (data_mode_)->setChecked (true); ui_->split_mode_button_group->button (rig_params_.split_mode_)->setChecked (true); @@ -1167,6 +1173,8 @@ void Configuration::impl::read_settings () jt9w_min_dt_ = settings_->value ("DTmin", -2.5).toFloat (); jt9w_max_dt_ = settings_->value ("DTmax", 5.).toFloat (); + type_2_msg_gen_ = settings_->value ("Type2MsgGen", QVariant::fromValue (Configuration::type_2_msg_3_full)).value (); + monitor_off_at_startup_ = settings_->value ("MonitorOFF", false).toBool (); monitor_last_used_ = settings_->value ("MonitorLastUsed", false).toBool (); spot_to_psk_reporter_ = settings_->value ("PSKReporter", false).toBool (); @@ -1252,6 +1260,7 @@ void Configuration::impl::write_settings () settings_->setValue ("ToneMult", jt9w_bw_mult_); settings_->setValue ("DTmin", jt9w_min_dt_); settings_->setValue ("DTmax", jt9w_max_dt_); + settings_->setValue ("Type2MsgGen", QVariant::fromValue (type_2_msg_gen_)); settings_->setValue ("MonitorOFF", monitor_off_at_startup_); settings_->setValue ("MonitorLastUsed", monitor_last_used_); settings_->setValue ("PSKReporter", spot_to_psk_reporter_); @@ -1605,6 +1614,7 @@ void Configuration::impl::accept () jt9w_bw_mult_ = ui_->jt9w_bandwidth_mult_combo_box->currentText ().toUInt (); jt9w_min_dt_ = static_cast (ui_->jt9w_min_dt_double_spin_box->value ()); jt9w_max_dt_ = static_cast (ui_->jt9w_max_dt_double_spin_box->value ()); + type_2_msg_gen_ = static_cast (ui_->type_2_msg_gen_combo_box->currentIndex ()); log_as_RTTY_ = ui_->log_as_RTTY_check_box->isChecked (); report_in_comments_ = ui_->report_in_comments_check_box->isChecked (); prompt_to_log_ = ui_->prompt_to_log_check_box->isChecked (); @@ -2420,8 +2430,11 @@ bool operator != (RigParams const& lhs, RigParams const& rhs) #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, Type2MsgGen); ENUM_CONVERSION_OPS_IMPL (Configuration, DataMode); +ENUM_CONVERSION_OPS_IMPL (Configuration, Type2MsgGen); diff --git a/Configuration.hpp b/Configuration.hpp index fc239c001..e04345060 100644 --- a/Configuration.hpp +++ b/Configuration.hpp @@ -54,7 +54,7 @@ class Configuration final : public QObject { Q_OBJECT; - Q_ENUMS (DataMode); + Q_ENUMS (DataMode Type2MsgGen); public: using MODE = Transceiver::MODE; @@ -62,6 +62,7 @@ public: using Frequency = Radio::Frequency; enum DataMode {data_mode_none, data_mode_USB, data_mode_data}; + enum Type2MsgGen {type_2_msg_1_full, type_2_msg_3_full, type_2_msg_5_only}; explicit Configuration (QSettings * settings, QWidget * parent = nullptr); ~Configuration (); @@ -113,6 +114,7 @@ public: unsigned jt9w_bw_mult () const; float jt9w_min_dt () const; float jt9w_max_dt () const; + Type2MsgGen type_2_msg_gen () const; QColor color_CQ () const; QColor color_MyCall () const; QColor color_TxMsg () const; @@ -186,13 +188,17 @@ private: }; Q_DECLARE_METATYPE (Configuration::DataMode); +Q_DECLARE_METATYPE (Configuration::Type2MsgGen); #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, Type2MsgGen); ENUM_CONVERSION_OPS_DECL (Configuration, DataMode); +ENUM_CONVERSION_OPS_DECL (Configuration, Type2MsgGen); #endif diff --git a/Configuration.ui b/Configuration.ui index 908dba149..696b50ec9 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -53,8 +53,18 @@ Station Details - - + + + + + M&y Grid: + + + grid_line_edit + + + + My C&all: @@ -64,14 +74,21 @@ - + + + + Maidenhead locator (only the first four characters are required). + + + + Station callsign. - + Qt::Horizontal @@ -84,20 +101,44 @@ - - - - M&y Grid: + + + + true - - grid_line_edit + + <html><head/><body><p>Type 2 compound callsigns are those with prefixes or suffixes not included in the allowed shortlist (See Help-&gt;Add-on prefixes and suffixes).</p><p>This option determines which generated messages should contain your full type 2 compound call sign rather than your base callsign. It only applies if you have a type 2 compound callsign.</p><p>This option controls the way the messages that are used to answer CQ calls are generated. Generated messages 6 (CQ) and 5 (73) will always contain your full callsign. The JT65 and JT9 protocols allow for some standard messages with your full call at the expense of another piece of information such as the DX call or your locator.</p><p>Choosing message 1 omits the DX callsign which may be an issue when replying to CQ calls. Choosing message 3 also omits the DX callsign and many versions of this and other software will not extract the report. Choosing neither means that your full callsign only goes in your message 5 (73) so your QSO partner my log the wrong callsign.</p><p>None of these options are perfect, message 3 is best but be aware your QSO partner may not log the report you send them.</p></body></html> + + 1 + + + + Full call in Tx1 + + + + + Full call in Tx3 + + + + + Full call in Tx5 only + + - - - - Maidenhead locator (only the first four characters are required). + + + + Message generation for type 2 compound callsign holders: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + type_2_msg_gen_combo_box @@ -1953,6 +1994,7 @@ soundcard changes configuration_tabs callsign_line_edit grid_line_edit + type_2_msg_gen_combo_box insert_blank_check_box miles_check_box TX_messages_check_box @@ -1961,6 +2003,7 @@ soundcard changes decoded_text_font_push_button monitor_off_check_box monitor_last_used_check_box + tx_QSY_check_box quick_call_check_box tx_QSY_check_box disable_TX_on_73_check_box @@ -2088,12 +2131,12 @@ soundcard changes - - - - + + + + diff --git a/decodedtext.cpp b/decodedtext.cpp index bb6583a5c..974ae4150 100644 --- a/decodedtext.cpp +++ b/decodedtext.cpp @@ -50,7 +50,7 @@ int DecodedText::snr() */ // find and extract any report. Returns true if this is a standard message -bool DecodedText::report(const QString myCall, /*mod*/QString& report) +bool DecodedText::report(QString const& myBaseCall, QString const& dxBaseCall, /*mod*/QString& report) { QString msg=_string.mid(column_qsoText); int i1=msg.indexOf("\r"); @@ -59,10 +59,16 @@ bool DecodedText::report(const QString myCall, /*mod*/QString& report) bool b = stdmsg_(msg.mid(0,22).toLatin1().constData(),22); // stdmsg is a fortran routine that packs the text, unpacks it and compares the result QStringList w=msg.split(" ",QString::SkipEmptyParts); - if(b and w[0]==myCall) + if(b && (w[0] == myBaseCall + || w[0].endsWith ("/" + myBaseCall) + || w[0].startsWith (myBaseCall + "/") + || (w.size () > 1 && !dxBaseCall.isEmpty () + && (w[1] == dxBaseCall + || w[1].endsWith ("/" + dxBaseCall) + || w[1].startsWith (dxBaseCall + "/"))))) { QString tt=""; - if(w.length()>=3) tt=w[2]; + if(w.size() > 2) tt=w[2]; bool ok; i1=tt.toInt(&ok); if (ok and i1>=-50 and i1<50) diff --git a/decodedtext.h b/decodedtext.h index 47dcd63a2..6d2639adc 100644 --- a/decodedtext.h +++ b/decodedtext.h @@ -67,7 +67,7 @@ public: int snr(); // find and extract any report. Returns true if this is a standard message - bool report(const QString myCall, /*mod*/QString& report); + bool report(QString const& myBaseCall, QString const& dxBaseCall, /*mod*/QString& report); // get the first text word, usually the call QString call(); diff --git a/displaytext.cpp b/displaytext.cpp index bf141ac0a..4922edd8f 100644 --- a/displaytext.cpp +++ b/displaytext.cpp @@ -119,7 +119,11 @@ void DisplayText::displayDecodedText(DecodedText decodedText, QString myCall, CQcall = true; bg=color_CQ.name(); } - if (myCall != "" and decodedText.indexOf(" " + myCall + " ") > 0) + if (myCall != "" and ( + decodedText.indexOf (" " + myCall + " ") >= 0 + or decodedText.indexOf (" " + myCall + "/") >= 0 + or decodedText.indexOf ("/" + myCall + " ") >= 0 + )) bg=color_MyCall.name(); // if enabled add the DXCC entity and B4 status to the end of the preformated text line t1 diff --git a/mainwindow.cpp b/mainwindow.cpp index e3149ea5c..9f32c1ab0 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -658,8 +658,18 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog ui->readFreq->setStyleSheet(""); ui->readFreq->setEnabled(false); + auto callsign = m_config.my_callsign (); + if (QDialog::Accepted == m_config.exec ()) { + if (m_config.my_callsign () != callsign) + { + morse_(const_cast (m_config.my_callsign ().toLatin1().constData()) + , const_cast (icw) + , &m_ncw + , m_config.my_callsign ().length()); + } + on_dxGridEntry_textChanged (m_hisGrid); // recalculate distances in case of units change enable_DXCC_entity (m_config.DXCC ()); // sets text window proportions and (re)inits the logbook @@ -786,6 +796,12 @@ void MainWindow::keyPressEvent( QKeyEvent *e ) //keyPressEvent case Qt::Key_F4: ui->dxCallEntry->setText(""); ui->dxGridEntry->setText(""); + m_hisCall=""; + m_hisGrid=""; + m_rptSent=""; + m_rptRcvd=""; + m_qsoStart=""; + m_qsoStop=""; genStdMsgs(""); if (1 == ui->tabWidget->currentIndex()) { @@ -1366,9 +1382,11 @@ void MainWindow::readFromStdout() //readFromStdout DecodedText decodedtext; decodedtext = t.replace("\n",""); //t.replace("\n","").mid(0,t.length()-4); + auto my_base_call = baseCall (m_config.my_callsign ()); + // the left band display ui->decodedTextBrowser->displayDecodedText (decodedtext - , m_config.my_callsign () + , my_base_call , m_config.DXCC () , m_logBook , m_config.color_CQ() @@ -1380,7 +1398,7 @@ void MainWindow::readFromStdout() //readFromStdout { // the right QSO window ui->decodedTextBrowser2->displayDecodedText(decodedtext - , m_config.my_callsign () + , my_base_call , false , m_logBook , m_config.color_CQ() @@ -1395,7 +1413,9 @@ void MainWindow::readFromStdout() //readFromStdout } // find and extract any report for myCall - bool stdMsg = decodedtext.report(m_config.my_callsign (),/*mod*/m_rptRcvd); + bool stdMsg = decodedtext.report(my_base_call + , baseCall (ui->dxCallEntry-> text ().toUpper ().trimmed ()) + , /*mod*/m_rptRcvd); // extract details and send to PSKreporter int nsec=QDateTime::currentMSecsSinceEpoch()/1000-m_secBandChanged; @@ -1900,6 +1920,16 @@ void MainWindow::doubleClickOnCall(bool shift, bool ctrl) QStringList t4=t3.split(" ",QString::SkipEmptyParts); if(t4.length() <5) return; //Skip the rest if no decoded text + QString hiscall; + QString hisgrid; + decodedtext.deCallAndGrid(/*out*/hiscall,hisgrid); + // basic valid call sign check i.e. contains at least one digit and + // one letter next to each other + if (!hiscall.contains (QRegularExpression {R"(\d[[:upper:]]|[[:upper:]]\d)"})) + { + return; + } + // only allow automatic mode changes when not transmitting if (!m_transmitting) { @@ -1938,11 +1968,13 @@ void MainWindow::doubleClickOnCall(bool shift, bool ctrl) } } + auto my_base_call = baseCall (m_config.my_callsign ()); + int i9=m_QSOText.indexOf(decodedtext.string()); if (i9<0 and !decodedtext.isTX()) { ui->decodedTextBrowser2->displayDecodedText(decodedtext - , m_config.my_callsign () + , my_base_call , false , m_logBook , m_config.color_CQ() @@ -1965,12 +1997,13 @@ void MainWindow::doubleClickOnCall(bool shift, bool ctrl) return; } - QString hiscall; - QString hisgrid; - decodedtext.deCallAndGrid(/*out*/hiscall,hisgrid); - if (hiscall != ui->dxCallEntry->text()) - ui->dxGridEntry->setText(""); - ui->dxCallEntry->setText(hiscall); + auto base_call = baseCall (hiscall); + if (base_call != baseCall (ui->dxCallEntry-> text ().toUpper ().trimmed ()) || base_call != hiscall) + { + // his base call different or his call more qualified + // i.e. compound version of same base call + ui->dxCallEntry->setText(hiscall); + } if (gridOK(hisgrid)) ui->dxGridEntry->setText(hisgrid); if (ui->dxGridEntry->text()=="") @@ -1987,7 +2020,10 @@ void MainWindow::doubleClickOnCall(bool shift, bool ctrl) genStdMsgs(rpt); // determine the appropriate response to the received msg - if(decodedtext.indexOf(m_config.my_callsign ())>=0) + auto dtext = " " + decodedtext.string () + " "; + if(dtext.contains (" " + my_base_call + " ") + || dtext.contains ("/" + my_base_call + " ") + || dtext.contains (" " + my_base_call + "/")) { if (t4.length()>=7 // enough fields for a normal msg and !gridOK(t4.at(7))) // but no grid on end of msg @@ -2057,6 +2093,15 @@ void MainWindow::doubleClickOnCall(bool shift, bool ctrl) void MainWindow::genStdMsgs(QString rpt) //genStdMsgs() { QString t; + if(m_config.my_callsign () !="" and m_config.my_grid () !="") + { + t="CQ " + m_config.my_callsign () + " " + m_config.my_grid ().mid(0,4); + msgtype(t, ui->tx6); + } + else + { + ui->tx6->setText(""); + } QString hisCall=ui->dxCallEntry->text().toUpper().trimmed(); ui->dxCallEntry->setText(hisCall); if(hisCall=="") { @@ -2067,11 +2112,6 @@ void MainWindow::genStdMsgs(QString rpt) //genStdMsgs() ui->tx3->setText(""); ui->tx4->setText(""); ui->tx5->setCurrentText(""); - ui->tx6->setText(""); - if(m_config.my_callsign () !="" and m_config.my_grid () !="") { - t="CQ " + m_config.my_callsign () + " " + m_config.my_grid ().mid(0,4); - msgtype(t, ui->tx6); - } ui->genMsg->setText(""); return; } @@ -2080,7 +2120,6 @@ void MainWindow::genStdMsgs(QString rpt) //genStdMsgs() QString t0=hisBase + " " + myBase + " "; t=t0 + m_config.my_grid ().mid(0,4); - // if(myBase!=m_config.my_callsign ()) t="DE " + m_config.my_callsign () + " " + m_config.my_grid ().mid(0,4); //### msgtype(t, ui->tx1); if(rpt == "") { t=t+" OOO"; @@ -2096,12 +2135,9 @@ void MainWindow::genStdMsgs(QString rpt) //genStdMsgs() t=t0 + "RRR"; msgtype(t, ui->tx4); t=t0 + "73"; - // if(myBase!=m_config.my_callsign ()) t="DE " + m_config.my_callsign () + " 73"; //### msgtype(t, ui->tx5->lineEdit ()); } - t="CQ " + m_config.my_callsign () + " " + m_config.my_grid ().mid(0,4); - msgtype(t, ui->tx6); if(m_config.my_callsign ()!=myBase) { if(shortList(m_config.my_callsign ())) { t=hisCall + " " + m_config.my_callsign (); @@ -2109,22 +2145,40 @@ void MainWindow::genStdMsgs(QString rpt) //genStdMsgs() t="CQ " + m_config.my_callsign (); msgtype(t, ui->tx6); } else { - t="DE " + m_config.my_callsign () + " " + m_config.my_grid ().mid(0,4); - msgtype(t, ui->tx2); + switch (m_config.type_2_msg_gen ()) + { + case Configuration::type_2_msg_1_full: + t="DE " + m_config.my_callsign () + " " + m_config.my_grid ().mid(0,4); + msgtype(t, ui->tx1); + t=t0 + "R" + rpt; + msgtype(t, ui->tx3); + break; + + case Configuration::type_2_msg_3_full: + t = t0 + m_config.my_grid ().mid(0,4); + msgtype(t, ui->tx1); + t="DE " + m_config.my_callsign () + " R" + rpt; + msgtype(t, ui->tx3); + break; + + case Configuration::type_2_msg_5_only: + t = t0 + m_config.my_grid ().mid(0,4); + msgtype(t, ui->tx1); + t=t0 + "R" + rpt; + msgtype(t, ui->tx3); + break; + } t="DE " + m_config.my_callsign () + " 73"; msgtype(t, ui->tx5->lineEdit ()); - t="CQ " + m_config.my_callsign () + " " + m_config.my_grid ().mid(0,4); - msgtype(t, ui->tx6); } } else { if(hisCall!=hisBase) { if(shortList(hisCall)) { - t=hisCall + " " + m_config.my_callsign (); + t=hisBase + " " + m_config.my_callsign () + " " + m_config.my_grid ().mid (0,4); msgtype(t, ui->tx1); - } else { - t=hisCall + " 73"; - msgtype(t, ui->tx5->lineEdit()); } + t=hisCall + " 73"; + msgtype(t, ui->tx5->lineEdit()); } } m_ntx=1;