Add the option to ALT+click a decoded CQ or QRZ message which only

moves the Rx  frequency to theirs, this facilitates  calling a station
who is busy and may have  many callers on their frequency. Updated the
corresponding mouse shortcuts help text.

Allow for times with seconds when parsing fast mode and FT8 decodes.

Exclude the RR73 grid square from  and grid validation or matching, it
is not a grid square any more as  far as WSJT-X is concerned, it is an
RRR substitute.

Add a  simple state  machine for  QSO progress  such that  replies and
auto-sequencing can be better controlled.

Get compound callsign edge cases working again and allow QSOs from and
to compound callsign holders working in as many situations as possible
including  auto-sequencing and  FT8 auto-reply  mode.  This  does mean
that a  "DE W6/K1ABC DM93"  type message close to  a callers Tx  or Rx
frequency will be taken  as a reply to a CQ call  despite it not being
explicitly addressed back to the  CQ caller. Compound callsigns should
work in MSK144 contest  mode also as well as in  short code modes with
some  minor  restrictions   (short  codes  will  not   be  used  where
configuration demands that  a message be used to send  a full compound
callsign).

Auto sequencing  has been made  generic such that  it can be  used for
more than one mode if desired.

Allow the use of free text messages to sign off in auto sequenced QSOs
without the message  being overwritten by the  sequencer. Double click
actions have  been added to the  Tx5 radio and push  buttons to revert
back to the default standard 73 message.

Make DisplayText  class interface  more idiomatic  C++ and  simplify a
bit.

Fixed  some  displayed widget  arrangements  for  different modes  and
sub-modes  so that  they  are  consistent when  starting  up and  when
switching mode or sub-mode.

This is  a big change which  has been extensively tested  but no doubt
there will also be some new defects introduced.

git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@7939 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
Bill Somerville 2017-07-24 19:27:23 +00:00
parent ba0228b173
commit 87ae336443
8 changed files with 533 additions and 376 deletions

View File

@ -3,6 +3,11 @@
#include <QStringList> #include <QStringList>
#include <QRegularExpression> #include <QRegularExpression>
extern "C" {
bool stdmsg_(const char* msg, int len);
}
QString DecodedText::CQersCall() QString DecodedText::CQersCall()
{ {
// extract the CQer's call TODO: does this work with all call formats? // extract the CQer's call TODO: does this work with all call formats?
@ -37,12 +42,12 @@ QString DecodedText::CQersCall()
bool DecodedText::isJT65() bool DecodedText::isJT65()
{ {
return _string.indexOf("#") == column_mode; return _string.indexOf("#") == column_mode + padding_;
} }
bool DecodedText::isJT9() bool DecodedText::isJT9()
{ {
return _string.indexOf("@") == column_mode; return _string.indexOf("@") == column_mode + padding_;
} }
bool DecodedText::isTX() bool DecodedText::isTX()
@ -53,7 +58,7 @@ bool DecodedText::isTX()
int DecodedText::frequencyOffset() int DecodedText::frequencyOffset()
{ {
return _string.mid(column_freq,4).toInt(); return _string.mid(column_freq + padding_,4).toInt();
} }
int DecodedText::snr() int DecodedText::snr()
@ -64,7 +69,7 @@ int DecodedText::snr()
float DecodedText::dt() float DecodedText::dt()
{ {
return _string.mid(column_dt,5).toFloat(); return _string.mid(column_dt + padding_,5).toFloat();
} }
/* /*
@ -79,7 +84,7 @@ float DecodedText::dt()
// find and extract any report. Returns true if this is a standard message // find and extract any report. Returns true if this is a standard message
bool DecodedText::report(QString const& myBaseCall, QString const& dxBaseCall, /*mod*/QString& report) bool DecodedText::report(QString const& myBaseCall, QString const& dxBaseCall, /*mod*/QString& report)
{ {
QString msg=_string.mid(column_qsoText).trimmed(); QString msg=_string.mid(column_qsoText + padding_).trimmed();
if(msg.length() < 1) return false; if(msg.length() < 1) return false;
msg = msg.left (22).remove (QRegularExpression {"[<>]"}); msg = msg.left (22).remove (QRegularExpression {"[<>]"});
int i1=msg.indexOf('\r'); int i1=msg.indexOf('\r');
@ -124,7 +129,7 @@ bool DecodedText::report(QString const& myBaseCall, QString const& dxBaseCall, /
QString DecodedText::call() QString DecodedText::call()
{ {
auto call = _string; auto call = _string;
call = call.replace (QRegularExpression {" CQ ([A-Z]{2,2}|[0-9]{3,3}) "}, " CQ_\\1 ").mid (column_qsoText); call = call.replace (QRegularExpression {" CQ ([A-Z]{2,2}|[0-9]{3,3}) "}, " CQ_\\1 ").mid (column_qsoText + padding_);
int i = call.indexOf(" "); int i = call.indexOf(" ");
return call.mid(0,i); return call.mid(0,i);
} }
@ -134,7 +139,7 @@ void DecodedText::deCallAndGrid(/*out*/QString& call, QString& grid)
{ {
auto msg = _string; auto msg = _string;
if(msg.mid(4,1)!=" ") msg=msg.mid(0,4)+msg.mid(6,-1); //Remove seconds from UTC if(msg.mid(4,1)!=" ") msg=msg.mid(0,4)+msg.mid(6,-1); //Remove seconds from UTC
msg = msg.replace (QRegularExpression {" CQ ([A-Z]{2,2}|[0-9]{3,3}) "}, " CQ_\\1 ").mid (column_qsoText); msg = msg.replace (QRegularExpression {" CQ ([A-Z]{2,2}|[0-9]{3,3}) "}, " CQ_\\1 ").mid (column_qsoText + padding_);
int i1 = msg.indexOf (" "); int i1 = msg.indexOf (" ");
call = msg.mid (i1 + 1); call = msg.mid (i1 + 1);
int i2 = call.indexOf (" "); int i2 = call.indexOf (" ");

View File

@ -15,79 +15,78 @@
/* /*
0123456789012345678901234567890123456789 0123456789012345678901234567890123456789
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
2343 -11 0.8 1259 # YV6BFE F6GUU R-08 2343 -11 0.8 1259 # YV6BFE F6GUU R-08
2343 -19 0.3 718 # VE6WQ SQ2NIJ -14 2343 -19 0.3 718 # VE6WQ SQ2NIJ -14
2343 -7 0.3 815 # KK4DSD W7VP -16 2343 -7 0.3 815 # KK4DSD W7VP -16
2343 -13 0.1 3627 @ CT1FBK IK5YZT R+02 2343 -13 0.1 3627 @ CT1FBK IK5YZT R+02
0605 Tx 1259 # CQ VK3ACF QF22 0605 Tx 1259 # CQ VK3ACF QF22
*/ */
class DecodedText class DecodedText
{ {
public: public:
// These define the columns in the decoded text where fields are to be found. void operator=(const QString &rhs)
// We rely on these columns being the same in the fortran code (lib/decoder.f90) that formats the decoded text {
enum Columns { column_time = 0, _string = rhs;
column_snr = 5, padding_ = _string.indexOf (" ") > 4 ? 2 : 0; // allow for seconds
column_dt = 9, };
column_freq = 14, void operator=(const QByteArray &rhs)
column_mode = 19, {
column_qsoText = 22 }; _string = rhs;
padding_ = _string.indexOf (" ") > 4 ? 2 : 0; // allow for seconds
};
void operator=(const QString &rhs) void operator+=(const QString &rhs)
{ {
_string = rhs; _string += rhs;
}; };
void operator=(const QByteArray &rhs)
{
_string = rhs;
};
void operator+=(const QString &rhs) QString string() { return _string; };
{
_string += rhs;
};
QString string() { return _string; }; int indexOf(QString s) { return _string.indexOf(s); };
int indexOf(QString s, int i) { return _string.indexOf(s,i); };
QString mid(int f, int t) { return _string.mid(f,t); };
QString left(int i) { return _string.left(i); };
int indexOf(QString s) { return _string.indexOf(s); }; void clear() { _string.clear(); };
int indexOf(QString s, int i) { return _string.indexOf(s,i); };
QString mid(int f, int t) { return _string.mid(f,t); };
QString left(int i) { return _string.left(i); };
void clear() { _string.clear(); }; QString CQersCall();
QString CQersCall(); bool isJT65();
bool isJT9();
bool isTX();
int frequencyOffset(); // hertz offset from the tuned dial or rx frequency, aka audio frequency
int snr();
float dt();
bool isJT65(); // find and extract any report. Returns true if this is a standard message
bool isJT9();
bool isTX();
int frequencyOffset(); // hertz offset from the tuned dial or rx frequency, aka audio frequency
int snr();
float dt();
// find and extract any report. Returns true if this is a standard message
bool report(QString const& myBaseCall, QString const& dxBaseCall, /*mod*/QString& report); bool report(QString const& myBaseCall, QString const& dxBaseCall, /*mod*/QString& report);
// get the first text word, usually the call // get the first message text word, usually the call
QString call(); QString call();
// get the second word, most likely the de call and the third word, most likely grid // get the second word, most likely the de call and the third word, most likely grid
void deCallAndGrid(/*out*/QString& call, QString& grid); void deCallAndGrid(/*out*/QString& call, QString& grid);
int timeInSeconds(); int timeInSeconds();
// returns a string of the SNR field with a leading + or - followed by two digits // returns a string of the SNR field with a leading + or - followed by two digits
QString report(); QString report();
private: private:
QString _string; // These define the columns in the decoded text where fields are to be found.
// We rely on these columns being the same in the fortran code (lib/decoder.f90) that formats the decoded text
enum Columns {column_time = 0,
column_snr = 5,
column_dt = 9,
column_freq = 14,
column_mode = 19,
column_qsoText = 22 };
QString _string;
int padding_;
}; };
extern "C" { bool stdmsg_(const char* msg, int len); }
#endif // DECODEDTEXT_H #endif // DECODEDTEXT_H

View File

@ -40,8 +40,8 @@ void DisplayText::setContentFont(QFont const& font)
void DisplayText::mouseDoubleClickEvent(QMouseEvent *e) void DisplayText::mouseDoubleClickEvent(QMouseEvent *e)
{ {
bool ctrl = (e->modifiers() & Qt::ControlModifier); bool ctrl = (e->modifiers() & Qt::ControlModifier);
bool shift = (e->modifiers() & Qt::ShiftModifier); bool alt = (e->modifiers() & Qt::AltModifier);
emit(selectCallsign(shift,ctrl)); emit(selectCallsign(alt,ctrl));
QTextEdit::mouseDoubleClickEvent(e); QTextEdit::mouseDoubleClickEvent(e);
} }
@ -72,24 +72,24 @@ void DisplayText::appendText(QString const& text, QString const& bg)
} }
void DisplayText::_appendDXCCWorkedB4(DecodedText& t1, QString& bg, QString DisplayText::_appendDXCCWorkedB4(QString message, QString const& callsign, QString * bg,
LogBook logBook, QColor color_CQ, LogBook logBook, QColor color_CQ,
QColor color_DXCC, QColor color_DXCC,
QColor color_NewCall) QColor color_NewCall)
{ {
QString call = t1.CQersCall (); QString call = callsign;
QString countryName; QString countryName;
bool callWorkedBefore; bool callWorkedBefore;
bool countryWorkedBefore; bool countryWorkedBefore;
if(call.length()==2) { if(call.length()==2) {
int i0=t1.indexOf("CQ "+call); int i0=message.indexOf("CQ "+call);
call=t1.mid(i0+6,-1); call=message.mid(i0+6,-1);
i0=call.indexOf(" "); i0=call.indexOf(" ");
call=call.mid(0,i0); call=call.mid(0,i0);
} }
if(call.length()<3) return; if(call.length()<3) return message;
if(!call.contains(QRegExp("[0-9]")) or !call.contains(QRegExp("[A-Z]"))) return; if(!call.contains(QRegExp("[0-9]")) or !call.contains(QRegExp("[A-Z]"))) return message;
logBook.match(/*in*/call,/*out*/countryName,callWorkedBefore,countryWorkedBefore); logBook.match(/*in*/call,/*out*/countryName,callWorkedBefore,countryWorkedBefore);
int charsAvail = 48; int charsAvail = 48;
@ -97,31 +97,31 @@ void DisplayText::_appendDXCCWorkedB4(DecodedText& t1, QString& bg,
// the decoder (seems) to always generate 41 chars. For a normal CQ call, the last five are spaces // the decoder (seems) to always generate 41 chars. For a normal CQ call, the last five are spaces
// TODO this magic 37 characters is also referenced in MainWindow::doubleClickOnCall() // TODO this magic 37 characters is also referenced in MainWindow::doubleClickOnCall()
int nmin=37; int nmin=37;
int i=t1.indexOf(" CQ "); int i=message.indexOf(" CQ ");
int k=t1.string().mid(i+4,3).toInt(); int k=message.mid(i+4,3).toInt();
if(k>0 and k<999) nmin += 4; if(k>0 and k<999) nmin += 4;
int s3 = t1.indexOf(" ",nmin); int s3 = message.indexOf(" ",nmin);
if (s3 < nmin) s3 = nmin; // always want at least the characters to position 35 if (s3 < nmin) s3 = nmin; // always want at least the characters to position 35
s3 += 1; // convert the index into a character count s3 += 1; // convert the index into a character count
t1 = t1.left(s3); // reduce trailing white space message = message.left(s3); // reduce trailing white space
charsAvail -= s3; charsAvail -= s3;
if (charsAvail > 4) if (charsAvail > 4)
{ {
if (!countryWorkedBefore) // therefore not worked call either if (!countryWorkedBefore) // therefore not worked call either
{ {
t1 += "!"; message += "!";
bg=color_DXCC.name(); *bg = color_DXCC.name();
} }
else else
if (!callWorkedBefore) // but have worked the country if (!callWorkedBefore) // but have worked the country
{ {
t1 += "~"; message += "~";
bg=color_NewCall.name(); *bg = color_NewCall.name();
} }
else else
{ {
t1 += " "; // have worked this call before message += " "; // have worked this call before
bg=color_CQ.name(); *bg = color_CQ.name();
} }
charsAvail -= 1; charsAvail -= 1;
@ -144,8 +144,9 @@ void DisplayText::_appendDXCCWorkedB4(DecodedText& t1, QString& bg,
countryName.replace ("Asiatic", "AS"); countryName.replace ("Asiatic", "AS");
countryName.replace ("European", "EU"); countryName.replace ("European", "EU");
countryName.replace ("African", "AF"); countryName.replace ("African", "AF");
t1 += countryName; message += countryName;
} }
return message;
} }
void DisplayText::displayDecodedText(DecodedText decodedText, QString myCall, void DisplayText::displayDecodedText(DecodedText decodedText, QString myCall,
@ -170,11 +171,13 @@ void DisplayText::displayDecodedText(DecodedText decodedText, QString myCall,
or decodedText.indexOf (" " + myCall + ">") >= 0)) { or decodedText.indexOf (" " + myCall + ">") >= 0)) {
bg=color_MyCall.name(); bg=color_MyCall.name();
} }
// if enabled add the DXCC entity and B4 status to the end of the preformated text line t1 // if enabled add the DXCC entity and B4 status to the end of the
// preformated text line t1
auto message = decodedText.string ();
if (displayDXCCEntity && CQcall) if (displayDXCCEntity && CQcall)
_appendDXCCWorkedB4(/*mod*/decodedText,bg,logBook,color_CQ, _appendDXCCWorkedB4 (message, decodedText.CQersCall (), &bg, logBook, color_CQ,
color_DXCC,color_NewCall); color_DXCC, color_NewCall);
appendText(decodedText.string(),bg); appendText (message, bg);
} }

View File

@ -23,7 +23,7 @@ public:
void displayQSY(QString text); void displayQSY(QString text);
signals: signals:
void selectCallsign(bool shift, bool ctrl); void selectCallsign(bool alt, bool ctrl);
public slots: public slots:
void appendText(QString const& text, QString const& bg = "white"); void appendText(QString const& text, QString const& bg = "white");
@ -32,7 +32,7 @@ protected:
void mouseDoubleClickEvent(QMouseEvent *e); void mouseDoubleClickEvent(QMouseEvent *e);
private: private:
void _appendDXCCWorkedB4(/*mod*/DecodedText& t1, QString &bg, LogBook logBook, QString _appendDXCCWorkedB4(QString message, QString const& callsign, QString * bg, LogBook logBook,
QColor color_CQ, QColor color_DXCC, QColor color_NewCall); QColor color_CQ, QColor color_DXCC, QColor color_NewCall);
QTextCharFormat m_charFormat; QTextCharFormat m_charFormat;

File diff suppressed because it is too large Load Diff

View File

@ -160,12 +160,14 @@ private slots:
void on_txrb3_toggled(bool status); void on_txrb3_toggled(bool status);
void on_txrb4_toggled(bool status); void on_txrb4_toggled(bool status);
void on_txrb5_toggled(bool status); void on_txrb5_toggled(bool status);
void on_txrb5_doubleClicked ();
void on_txrb6_toggled(bool status); void on_txrb6_toggled(bool status);
void on_txb1_clicked(); void on_txb1_clicked();
void on_txb2_clicked(); void on_txb2_clicked();
void on_txb3_clicked(); void on_txb3_clicked();
void on_txb4_clicked(); void on_txb4_clicked();
void on_txb5_clicked(); void on_txb5_clicked();
void on_txb5_doubleClicked ();
void on_txb6_clicked(); void on_txb6_clicked();
void on_lookupButton_clicked(); void on_lookupButton_clicked();
void on_addButton_clicked(); void on_addButton_clicked();
@ -299,7 +301,7 @@ private:
private: private:
void astroUpdate (); void astroUpdate ();
void writeAllTxt(QString message); void writeAllTxt(QString message);
void FT8_AutoSeq(QString message); void auto_sequence (QString const& message, unsigned tolerance);
void hideMenus(bool b); void hideMenus(bool b);
NetworkAccessManager m_network_manager; NetworkAccessManager m_network_manager;
@ -446,6 +448,17 @@ private:
bool m_bQRAsyncWarned; bool m_bQRAsyncWarned;
bool m_bDoubleClicked; bool m_bDoubleClicked;
bool m_bCallingCQ; bool m_bCallingCQ;
bool m_bAutoReply;
enum
{
CALLING,
REPLYING,
REPORT,
ROGER_REPORT,
ROGERS,
SIGNOFF
}
m_QSOProgress;
int m_ihsym; int m_ihsym;
int m_nzap; int m_nzap;
@ -557,7 +570,7 @@ private:
void writeSettings(); void writeSettings();
void createStatusBar(); void createStatusBar();
void updateStatusBar(); void updateStatusBar();
void genStdMsgs(QString rpt); void genStdMsgs(QString rpt, bool unconditional = false);
void genCQMsg(); void genCQMsg();
void clearDX (); void clearDX ();
void lookup(); void lookup();
@ -573,7 +586,7 @@ private:
void pskPost(DecodedText decodedtext); void pskPost(DecodedText decodedtext);
void displayDialFrequency (); void displayDialFrequency ();
void transmitDisplay (bool); void transmitDisplay (bool);
void processMessage(QString const& messages, qint32 position, bool ctrl); void processMessage(QString const& messages, qint32 position, bool ctrl = false, bool alt = false);
void replyToCQ (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text); void replyToCQ (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text);
void replayDecodes (); void replayDecodes ();
void postDecode (bool is_new, QString const& message); void postDecode (bool is_new, QString const& message);

View File

@ -1292,9 +1292,9 @@ list. The list can be maintained in Settings (F2).</string>
</widget> </widget>
</item> </item>
<item row="5" column="1" alignment="Qt::AlignHCenter|Qt::AlignVCenter"> <item row="5" column="1" alignment="Qt::AlignHCenter|Qt::AlignVCenter">
<widget class="QRadioButton" name="txrb5"> <widget class="DoubleClickableRadioButton" name="txrb5">
<property name="toolTip"> <property name="toolTip">
<string>Send this message in next Tx interval</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Send this message in next Tx interval&lt;/p&gt;&lt;p&gt;Double-click to reset to the standard 73 message&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
@ -1308,7 +1308,7 @@ list. The list can be maintained in Settings (F2).</string>
</widget> </widget>
</item> </item>
<item row="5" column="2"> <item row="5" column="2">
<widget class="QPushButton" name="txb5"> <widget class="DoubleClickablePushButton" name="txb5">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>30</width> <width>30</width>
@ -1316,7 +1316,7 @@ list. The list can be maintained in Settings (F2).</string>
</size> </size>
</property> </property>
<property name="toolTip"> <property name="toolTip">
<string>Switch to this Tx message NOW</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Switch to this Tx message NOW&lt;/p&gt;&lt;p&gt;Double-click to reset to the standard 73 message&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Tx &amp;5</string> <string>Tx &amp;5</string>
@ -3018,6 +3018,16 @@ QPushButton[state=&quot;ok&quot;] {
<extends>QSpinBox</extends> <extends>QSpinBox</extends>
<header>RestrictedSpinBox.hpp</header> <header>RestrictedSpinBox.hpp</header>
</customwidget> </customwidget>
<customwidget>
<class>DoubleClickableRadioButton</class>
<extends>QRadioButton</extends>
<header>DoubleClickableRadioButton.hpp</header>
</customwidget>
<customwidget>
<class>DoubleClickablePushButton</class>
<extends>QPushButton</extends>
<header>DoubleClickablePushButton.hpp</header>
</customwidget>
</customwidgets> </customwidgets>
<tabstops> <tabstops>
<tabstop>logQSOButton</tabstop> <tabstop>logQSOButton</tabstop>

View File

@ -18,7 +18,10 @@
locator to Dx Grid; change Rx and Tx frequencies to<br/> locator to Dx Grid; change Rx and Tx frequencies to<br/>
decoded signal's frequency; generate standard messages.<br/> decoded signal's frequency; generate standard messages.<br/>
If first callsign is your own, Tx frequency is not<br/> If first callsign is your own, Tx frequency is not<br/>
changed unless Ctrl is held down when double-clicking. changed unless Ctrl is held down when double-clicking.<br/>
<br/>
Hold down Alt to only move the Rx frequency when<br/>
when double-clicking to reply to a CQ or QRZ caller.
</td> </td>
</tr> </tr>
<tr> <tr>