mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-12-23 19:25:37 -05:00
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:
parent
ba0228b173
commit
87ae336443
@ -3,6 +3,11 @@
|
||||
#include <QStringList>
|
||||
#include <QRegularExpression>
|
||||
|
||||
|
||||
extern "C" {
|
||||
bool stdmsg_(const char* msg, int len);
|
||||
}
|
||||
|
||||
QString DecodedText::CQersCall()
|
||||
{
|
||||
// extract the CQer's call TODO: does this work with all call formats?
|
||||
@ -37,12 +42,12 @@ QString DecodedText::CQersCall()
|
||||
|
||||
bool DecodedText::isJT65()
|
||||
{
|
||||
return _string.indexOf("#") == column_mode;
|
||||
return _string.indexOf("#") == column_mode + padding_;
|
||||
}
|
||||
|
||||
bool DecodedText::isJT9()
|
||||
{
|
||||
return _string.indexOf("@") == column_mode;
|
||||
return _string.indexOf("@") == column_mode + padding_;
|
||||
}
|
||||
|
||||
bool DecodedText::isTX()
|
||||
@ -53,7 +58,7 @@ bool DecodedText::isTX()
|
||||
|
||||
int DecodedText::frequencyOffset()
|
||||
{
|
||||
return _string.mid(column_freq,4).toInt();
|
||||
return _string.mid(column_freq + padding_,4).toInt();
|
||||
}
|
||||
|
||||
int DecodedText::snr()
|
||||
@ -64,7 +69,7 @@ int DecodedText::snr()
|
||||
|
||||
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
|
||||
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;
|
||||
msg = msg.left (22).remove (QRegularExpression {"[<>]"});
|
||||
int i1=msg.indexOf('\r');
|
||||
@ -124,7 +129,7 @@ bool DecodedText::report(QString const& myBaseCall, QString const& dxBaseCall, /
|
||||
QString DecodedText::call()
|
||||
{
|
||||
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(" ");
|
||||
return call.mid(0,i);
|
||||
}
|
||||
@ -134,7 +139,7 @@ void DecodedText::deCallAndGrid(/*out*/QString& call, QString& grid)
|
||||
{
|
||||
auto msg = _string;
|
||||
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 (" ");
|
||||
call = msg.mid (i1 + 1);
|
||||
int i2 = call.indexOf (" ");
|
||||
|
105
decodedtext.h
105
decodedtext.h
@ -15,79 +15,78 @@
|
||||
|
||||
/*
|
||||
0123456789012345678901234567890123456789
|
||||
^ ^ ^ ^ ^ ^
|
||||
2343 -11 0.8 1259 # YV6BFE F6GUU R-08
|
||||
2343 -19 0.3 718 # VE6WQ SQ2NIJ -14
|
||||
2343 -7 0.3 815 # KK4DSD W7VP -16
|
||||
2343 -13 0.1 3627 @ CT1FBK IK5YZT R+02
|
||||
^ ^ ^ ^ ^ ^
|
||||
2343 -11 0.8 1259 # YV6BFE F6GUU R-08
|
||||
2343 -19 0.3 718 # VE6WQ SQ2NIJ -14
|
||||
2343 -7 0.3 815 # KK4DSD W7VP -16
|
||||
2343 -13 0.1 3627 @ CT1FBK IK5YZT R+02
|
||||
|
||||
0605 Tx 1259 # CQ VK3ACF QF22
|
||||
0605 Tx 1259 # CQ VK3ACF QF22
|
||||
*/
|
||||
|
||||
class DecodedText
|
||||
{
|
||||
public:
|
||||
// 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 };
|
||||
void operator=(const QString &rhs)
|
||||
{
|
||||
_string = rhs;
|
||||
padding_ = _string.indexOf (" ") > 4 ? 2 : 0; // allow for seconds
|
||||
};
|
||||
void operator=(const QByteArray &rhs)
|
||||
{
|
||||
_string = rhs;
|
||||
padding_ = _string.indexOf (" ") > 4 ? 2 : 0; // allow for seconds
|
||||
};
|
||||
|
||||
void operator=(const QString &rhs)
|
||||
{
|
||||
_string = rhs;
|
||||
};
|
||||
void operator=(const QByteArray &rhs)
|
||||
{
|
||||
_string = rhs;
|
||||
};
|
||||
void operator+=(const QString &rhs)
|
||||
{
|
||||
_string += rhs;
|
||||
};
|
||||
|
||||
void operator+=(const QString &rhs)
|
||||
{
|
||||
_string += rhs;
|
||||
};
|
||||
QString string() { return _string; };
|
||||
|
||||
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); };
|
||||
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(); };
|
||||
|
||||
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();
|
||||
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
|
||||
// find and extract any report. Returns true if this is a standard message
|
||||
bool report(QString const& myBaseCall, QString const& dxBaseCall, /*mod*/QString& report);
|
||||
|
||||
// get the first text word, usually the call
|
||||
QString call();
|
||||
// get the first message text word, usually the call
|
||||
QString call();
|
||||
|
||||
// get the second word, most likely the de call and the third word, most likely grid
|
||||
void deCallAndGrid(/*out*/QString& call, QString& grid);
|
||||
// get the second word, most likely the de call and the third word, most likely 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
|
||||
QString report();
|
||||
// returns a string of the SNR field with a leading + or - followed by two digits
|
||||
QString report();
|
||||
|
||||
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
|
||||
|
@ -40,8 +40,8 @@ void DisplayText::setContentFont(QFont const& font)
|
||||
void DisplayText::mouseDoubleClickEvent(QMouseEvent *e)
|
||||
{
|
||||
bool ctrl = (e->modifiers() & Qt::ControlModifier);
|
||||
bool shift = (e->modifiers() & Qt::ShiftModifier);
|
||||
emit(selectCallsign(shift,ctrl));
|
||||
bool alt = (e->modifiers() & Qt::AltModifier);
|
||||
emit(selectCallsign(alt,ctrl));
|
||||
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,
|
||||
QColor color_DXCC,
|
||||
QColor color_NewCall)
|
||||
{
|
||||
QString call = t1.CQersCall ();
|
||||
QString call = callsign;
|
||||
QString countryName;
|
||||
bool callWorkedBefore;
|
||||
bool countryWorkedBefore;
|
||||
|
||||
if(call.length()==2) {
|
||||
int i0=t1.indexOf("CQ "+call);
|
||||
call=t1.mid(i0+6,-1);
|
||||
int i0=message.indexOf("CQ "+call);
|
||||
call=message.mid(i0+6,-1);
|
||||
i0=call.indexOf(" ");
|
||||
call=call.mid(0,i0);
|
||||
}
|
||||
if(call.length()<3) return;
|
||||
if(!call.contains(QRegExp("[0-9]")) or !call.contains(QRegExp("[A-Z]"))) return;
|
||||
if(call.length()<3) return message;
|
||||
if(!call.contains(QRegExp("[0-9]")) or !call.contains(QRegExp("[A-Z]"))) return message;
|
||||
|
||||
logBook.match(/*in*/call,/*out*/countryName,callWorkedBefore,countryWorkedBefore);
|
||||
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
|
||||
// TODO this magic 37 characters is also referenced in MainWindow::doubleClickOnCall()
|
||||
int nmin=37;
|
||||
int i=t1.indexOf(" CQ ");
|
||||
int k=t1.string().mid(i+4,3).toInt();
|
||||
int i=message.indexOf(" CQ ");
|
||||
int k=message.mid(i+4,3).toInt();
|
||||
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
|
||||
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;
|
||||
if (charsAvail > 4)
|
||||
{
|
||||
if (!countryWorkedBefore) // therefore not worked call either
|
||||
{
|
||||
t1 += "!";
|
||||
bg=color_DXCC.name();
|
||||
message += "!";
|
||||
*bg = color_DXCC.name();
|
||||
}
|
||||
else
|
||||
if (!callWorkedBefore) // but have worked the country
|
||||
{
|
||||
t1 += "~";
|
||||
bg=color_NewCall.name();
|
||||
message += "~";
|
||||
*bg = color_NewCall.name();
|
||||
}
|
||||
else
|
||||
{
|
||||
t1 += " "; // have worked this call before
|
||||
bg=color_CQ.name();
|
||||
message += " "; // have worked this call before
|
||||
*bg = color_CQ.name();
|
||||
}
|
||||
charsAvail -= 1;
|
||||
|
||||
@ -144,8 +144,9 @@ void DisplayText::_appendDXCCWorkedB4(DecodedText& t1, QString& bg,
|
||||
countryName.replace ("Asiatic", "AS");
|
||||
countryName.replace ("European", "EU");
|
||||
countryName.replace ("African", "AF");
|
||||
t1 += countryName;
|
||||
message += countryName;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
void DisplayText::displayDecodedText(DecodedText decodedText, QString myCall,
|
||||
@ -170,11 +171,13 @@ void DisplayText::displayDecodedText(DecodedText decodedText, QString myCall,
|
||||
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
|
||||
// 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)
|
||||
_appendDXCCWorkedB4(/*mod*/decodedText,bg,logBook,color_CQ,
|
||||
color_DXCC,color_NewCall);
|
||||
appendText(decodedText.string(),bg);
|
||||
_appendDXCCWorkedB4 (message, decodedText.CQersCall (), &bg, logBook, color_CQ,
|
||||
color_DXCC, color_NewCall);
|
||||
appendText (message, bg);
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
void displayQSY(QString text);
|
||||
|
||||
signals:
|
||||
void selectCallsign(bool shift, bool ctrl);
|
||||
void selectCallsign(bool alt, bool ctrl);
|
||||
|
||||
public slots:
|
||||
void appendText(QString const& text, QString const& bg = "white");
|
||||
@ -32,7 +32,7 @@ protected:
|
||||
void mouseDoubleClickEvent(QMouseEvent *e);
|
||||
|
||||
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);
|
||||
|
||||
QTextCharFormat m_charFormat;
|
||||
|
690
mainwindow.cpp
690
mainwindow.cpp
File diff suppressed because it is too large
Load Diff
19
mainwindow.h
19
mainwindow.h
@ -160,12 +160,14 @@ private slots:
|
||||
void on_txrb3_toggled(bool status);
|
||||
void on_txrb4_toggled(bool status);
|
||||
void on_txrb5_toggled(bool status);
|
||||
void on_txrb5_doubleClicked ();
|
||||
void on_txrb6_toggled(bool status);
|
||||
void on_txb1_clicked();
|
||||
void on_txb2_clicked();
|
||||
void on_txb3_clicked();
|
||||
void on_txb4_clicked();
|
||||
void on_txb5_clicked();
|
||||
void on_txb5_doubleClicked ();
|
||||
void on_txb6_clicked();
|
||||
void on_lookupButton_clicked();
|
||||
void on_addButton_clicked();
|
||||
@ -299,7 +301,7 @@ private:
|
||||
private:
|
||||
void astroUpdate ();
|
||||
void writeAllTxt(QString message);
|
||||
void FT8_AutoSeq(QString message);
|
||||
void auto_sequence (QString const& message, unsigned tolerance);
|
||||
void hideMenus(bool b);
|
||||
|
||||
NetworkAccessManager m_network_manager;
|
||||
@ -446,6 +448,17 @@ private:
|
||||
bool m_bQRAsyncWarned;
|
||||
bool m_bDoubleClicked;
|
||||
bool m_bCallingCQ;
|
||||
bool m_bAutoReply;
|
||||
enum
|
||||
{
|
||||
CALLING,
|
||||
REPLYING,
|
||||
REPORT,
|
||||
ROGER_REPORT,
|
||||
ROGERS,
|
||||
SIGNOFF
|
||||
}
|
||||
m_QSOProgress;
|
||||
|
||||
int m_ihsym;
|
||||
int m_nzap;
|
||||
@ -557,7 +570,7 @@ private:
|
||||
void writeSettings();
|
||||
void createStatusBar();
|
||||
void updateStatusBar();
|
||||
void genStdMsgs(QString rpt);
|
||||
void genStdMsgs(QString rpt, bool unconditional = false);
|
||||
void genCQMsg();
|
||||
void clearDX ();
|
||||
void lookup();
|
||||
@ -573,7 +586,7 @@ private:
|
||||
void pskPost(DecodedText decodedtext);
|
||||
void displayDialFrequency ();
|
||||
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 replayDecodes ();
|
||||
void postDecode (bool is_new, QString const& message);
|
||||
|
@ -1292,9 +1292,9 @@ list. The list can be maintained in Settings (F2).</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" alignment="Qt::AlignHCenter|Qt::AlignVCenter">
|
||||
<widget class="QRadioButton" name="txrb5">
|
||||
<widget class="DoubleClickableRadioButton" name="txrb5">
|
||||
<property name="toolTip">
|
||||
<string>Send this message in next Tx interval</string>
|
||||
<string><html><head/><body><p>Send this message in next Tx interval</p><p>Double-click to reset to the standard 73 message</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
@ -1308,7 +1308,7 @@ list. The list can be maintained in Settings (F2).</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QPushButton" name="txb5">
|
||||
<widget class="DoubleClickablePushButton" name="txb5">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
@ -1316,7 +1316,7 @@ list. The list can be maintained in Settings (F2).</string>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Switch to this Tx message NOW</string>
|
||||
<string><html><head/><body><p>Switch to this Tx message NOW</p><p>Double-click to reset to the standard 73 message</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Tx &5</string>
|
||||
@ -3018,6 +3018,16 @@ QPushButton[state="ok"] {
|
||||
<extends>QSpinBox</extends>
|
||||
<header>RestrictedSpinBox.hpp</header>
|
||||
</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>
|
||||
<tabstops>
|
||||
<tabstop>logQSOButton</tabstop>
|
||||
|
@ -18,7 +18,10 @@
|
||||
locator to Dx Grid; change Rx and Tx frequencies to<br/>
|
||||
decoded signal's frequency; generate standard messages.<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>
|
||||
</tr>
|
||||
<tr>
|
||||
|
Loading…
Reference in New Issue
Block a user