Merge branch 'support-2.3.1' into release-2.4.0

This commit is contained in:
Bill Somerville 2021-03-03 23:58:39 +00:00
commit 22f1ba6a6d
No known key found for this signature in database
GPG Key ID: D864B06D1E81618F
56 changed files with 764 additions and 616 deletions

View File

@ -16,11 +16,15 @@ namespace
DecodedText::DecodedText (QString const& the_string) DecodedText::DecodedText (QString const& the_string)
: string_ {the_string.left (the_string.indexOf (QChar::Nbsp))} // discard appended info : string_ {the_string.left (the_string.indexOf (QChar::Nbsp))} // discard appended info
, clean_string_ {string_}
, padding_ {string_.indexOf (" ") > 4 ? 2 : 0} // allow for , padding_ {string_.indexOf (" ") > 4 ? 2 : 0} // allow for
// seconds // seconds
, message_ {string_.mid (column_qsoText + padding_).trimmed ()} , message_ {string_.mid (column_qsoText + padding_).trimmed ()}
, is_standard_ {false} , is_standard_ {false}
{ {
// discard appended AP info
clean_string_.replace (QRegularExpression {R"(^(.*)(?:(?:\?\s)?a[0-9].*)$)"}, "\\1");
// qDebug () << "DecodedText: the_string:" << the_string << "Nbsp pos:" << the_string.indexOf (QChar::Nbsp); // qDebug () << "DecodedText: the_string:" << the_string << "Nbsp pos:" << the_string.indexOf (QChar::Nbsp);
if (message_.length() >= 1) if (message_.length() >= 1)
{ {

View File

@ -32,6 +32,7 @@ public:
explicit DecodedText (QString const& message); explicit DecodedText (QString const& message);
QString string() const { return string_; }; QString string() const { return string_; };
QString clean_string() const { return clean_string_; };
QStringList messageWords () const; QStringList messageWords () const;
int indexOf(QString s) const { return string_.indexOf(s); }; int indexOf(QString s) const { return string_.indexOf(s); };
int indexOf(QString s, int i) const { return string_.indexOf(s,i); }; int indexOf(QString s, int i) const { return string_.indexOf(s,i); };
@ -76,6 +77,7 @@ private:
column_qsoText = 22 }; column_qsoText = 22 };
QString string_; QString string_;
QString clean_string_;
int padding_; int padding_;
QString message_; QString message_;
QString message0_; QString message0_;

View File

@ -576,20 +576,28 @@ void MultiSettings::impl::select_configuration (QString const& target_name)
{ {
if (main_window_ && target_name != current_) if (main_window_ && target_name != current_)
{ {
bool changed {false};
{ {
auto const& current_group = settings_.group (); auto const& current_group = settings_.group ();
if (current_group.size ()) settings_.endGroup (); if (current_group.size ()) settings_.endGroup ();
// position to the alternative settings // position to the alternative settings
SettingsGroup alternatives {&settings_, multi_settings_root_group}; SettingsGroup alternatives {&settings_, multi_settings_root_group};
// save the target settings if (settings_.childGroups ().contains (target_name))
SettingsGroup target_group {&settings_, target_name}; {
new_settings_ = get_settings (); changed = true;
// save the target settings
SettingsGroup target_group {&settings_, target_name};
new_settings_ = get_settings ();
}
if (current_group.size ()) settings_.beginGroup (current_group); if (current_group.size ()) settings_.beginGroup (current_group);
} }
// and set up the restart if (changed)
current_ = target_name; {
Q_EMIT parent_->configurationNameChanged (unescape_ampersands (current_)); // and set up the restart
restart (RepositionType::save_and_replace); current_ = target_name;
Q_EMIT parent_->configurationNameChanged (unescape_ampersands (current_));
restart (RepositionType::save_and_replace);
}
} }
} }

View File

@ -117,7 +117,7 @@ SampleDownloader::impl::impl (QSettings * settings
main_layout_.addLayout (&left_layout_, 0, 0); main_layout_.addLayout (&left_layout_, 0, 0);
main_layout_.addWidget (&button_box_, 0, 1); main_layout_.addWidget (&button_box_, 0, 1);
main_layout_.addWidget (&details_widget_, 1, 0, 1, 2); main_layout_.addWidget (&details_widget_, 1, 0, 1, 2);
main_layout_.setRowStretch (1, 2); main_layout_.setRowStretch (0, 2);
setLayout (&main_layout_); setLayout (&main_layout_);
connect (&button_box_, &QDialogButtonBox::clicked, this, &SampleDownloader::impl::button_clicked); connect (&button_box_, &QDialogButtonBox::clicked, this, &SampleDownloader::impl::button_clicked);

View File

@ -49,6 +49,8 @@ Directory::Directory (Configuration const * configuration
setColumnCount (2); setColumnCount (2);
setHeaderLabels ({tr ("File"), tr ("Progress")}); setHeaderLabels ({tr ("File"), tr ("Progress")});
headerItem ()->setTextAlignment (0, Qt::AlignHCenter);
headerItem ()->setTextAlignment (1, Qt::AlignHCenter);
header ()->setSectionResizeMode (QHeaderView::ResizeToContents); header ()->setSectionResizeMode (QHeaderView::ResizeToContents);
setItemDelegate (&item_delegate_); setItemDelegate (&item_delegate_);
@ -294,14 +296,15 @@ void Directory::update (QTreeWidgetItem * item)
int counted {0}; int counted {0};
// get the count, progress and size of children // get the count, progress and size of children
int items {recurse_children (item, &counted, &bytes, &max)}; // int items {recurse_children (item, &counted, &bytes, &max)};
recurse_children (item, &counted, &bytes, &max);
// estimate size of items not yet downloaded as average of // estimate size of items not yet downloaded as average of
// those actually present // those actually present
if (counted) // if (counted)
{ // {
max += (items - counted) * max / counted; // max += (items - counted) * max / counted;
} // }
// save as our progress // save as our progress
item->setData (1, Qt::UserRole, max); item->setData (1, Qt::UserRole, max);

View File

@ -14,28 +14,42 @@ void DirectoryDelegate::paint (QPainter * painter, QStyleOptionViewItem const& o
{ {
if (1 == index.column ()) if (1 == index.column ())
{ {
QStyleOptionProgressBar progress_bar_option;
progress_bar_option.rect = option.rect;
progress_bar_option.state = QStyle::State_Enabled;
progress_bar_option.direction = QApplication::layoutDirection ();
progress_bar_option.fontMetrics = QApplication::fontMetrics ();
progress_bar_option.minimum = 0;
progress_bar_option.maximum = 100;
auto progress = index.data ().toLongLong (); auto progress = index.data ().toLongLong ();
qint64 percent;
if (progress > 0) if (progress > 0)
{ {
auto percent = int (progress * 100 / index.data (Qt::UserRole).toLongLong ()); percent = int (progress * 100 / index.data (Qt::UserRole).toLongLong ());
progress_bar_option.progress = percent; }
progress_bar_option.text = QString::number (percent) + '%'; #if !defined (Q_OS_DARWIN)
progress_bar_option.textVisible = true; QStyleOptionProgressBar progress_option;
progress_bar_option.textAlignment = Qt::AlignCenter; auto control_element = QStyle::CE_ProgressBar;
progress_option.minimum = 0;
progress_option.maximum = 100;
progress_option.textAlignment = Qt::AlignCenter;
if (progress > 0)
{
progress_option.progress = percent;
progress_option.textVisible = true;
} }
else else
{ {
// not started // not started
progress_bar_option.progress = -1; progress_option.progress = -1;
} }
QApplication::style ()->drawControl (QStyle::CE_ProgressBar, &progress_bar_option, painter); #else
// workaround for broken QProgressBar item delegates on macOS
QStyleOptionViewItem progress_option;
auto control_element = QStyle::CE_ItemViewItem;
progress_option.displayAlignment = Qt::AlignHCenter;
progress_option.index = index;
progress_option.features = QStyleOptionViewItem::HasDisplay;
#endif
progress_option.rect = option.rect;
progress_option.state = QStyle::State_Enabled;
progress_option.direction = QApplication::layoutDirection ();
progress_option.fontMetrics = QApplication::fontMetrics ();
progress_option.text = QString::number (progress > 0 ? percent : 0) + '%';
QApplication::style ()->drawControl (control_element, &progress_option, painter);
} }
else else
{ {

View File

@ -27,7 +27,12 @@ FileNode::FileNode (QTreeWidgetItem * parent
void FileNode::error (QString const& title, QString const& message) void FileNode::error (QString const& title, QString const& message)
{ {
MessageBox::warning_message (treeWidget (), title, message); if (MessageBox::Retry == MessageBox::warning_message (treeWidget (), title, message
, QString {}, MessageBox::Cancel | MessageBox::Retry
, MessageBox::Cancel))
{
sync (true);
}
} }
bool FileNode::sync (bool local) bool FileNode::sync (bool local)

View File

@ -436,7 +436,11 @@ HamlibTransceiver::HamlibTransceiver (logger_type * logger,
{ {
m_->set_conf ("ptt_type", "RTS"); m_->set_conf ("ptt_type", "RTS");
} }
set_conf ("ptt_share", "1");
} }
// do this late to allow any configuration option to be overriden
load_user_settings ();
} }
HamlibTransceiver::HamlibTransceiver (logger_type * logger, HamlibTransceiver::HamlibTransceiver (logger_type * logger,
@ -453,52 +457,7 @@ HamlibTransceiver::HamlibTransceiver (logger_type * logger,
// m_->rig_->state.obj = this; // m_->rig_->state.obj = this;
// if (!is_dummy_)
// user defined Hamlib settings
//
auto settings_file_name = QStandardPaths::locate (QStandardPaths::AppConfigLocation
, "hamlib_settings.json");
if (!settings_file_name.isEmpty ())
{
QFile settings_file {settings_file_name};
qDebug () << "Using Hamlib settings file:" << settings_file_name;
if (settings_file.open (QFile::ReadOnly))
{
QJsonParseError status;
auto settings_doc = QJsonDocument::fromJson (settings_file.readAll (), &status);
if (status.error)
{
throw error {tr ("Hamlib settings file error: %1 at character offset %2")
.arg (status.errorString ()).arg (status.offset)};
}
qDebug () << "Hamlib settings JSON:" << settings_doc.toJson ();
if (!settings_doc.isObject ())
{
throw error {tr ("Hamlib settings file error: top level must be a JSON object")};
}
auto const& settings = settings_doc.object ();
//
// configuration settings
//
auto const& config = settings["config"];
if (!config.isUndefined ())
{
if (!config.isObject ())
{
throw error {tr ("Hamlib settings file error: config must be a JSON object")};
}
auto const& config_list = config.toObject ();
for (auto item = config_list.constBegin (); item != config_list.constEnd (); ++item)
{
m_->set_conf (item.key ().toLocal8Bit ().constData ()
, (*item).toVariant ().toString ().toLocal8Bit ().constData ());
}
}
}
}
if (!m_->is_dummy_)
{ {
switch (rig_get_caps_int (m_->model_, RIG_CAPS_PORT_TYPE)) switch (rig_get_caps_int (m_->model_, RIG_CAPS_PORT_TYPE))
{ {
@ -592,17 +551,69 @@ HamlibTransceiver::HamlibTransceiver (logger_type * logger,
{ {
m_->set_conf ("ptt_type", "RTS"); m_->set_conf ("ptt_type", "RTS");
} }
set_conf ("ptt_share", "1");
} }
// Make Icom CAT split commands less glitchy // Make Icom CAT split commands less glitchy
m_->set_conf ("no_xchg", "1"); m_->set_conf ("no_xchg", "1");
// do this late to allow any configuration option to be overriden
load_user_settings ();
// would be nice to get events but not supported on Windows and also not on a lot of rigs // would be nice to get events but not supported on Windows and also not on a lot of rigs
// rig_set_freq_callback (m_->rig_.data (), &frequency_change_callback, this); // rig_set_freq_callback (m_->rig_.data (), &frequency_change_callback, this);
} }
HamlibTransceiver::~HamlibTransceiver () = default; HamlibTransceiver::~HamlibTransceiver () = default;
void HamlibTransceiver::load_user_settings ()
{
//
// user defined Hamlib settings
//
auto settings_file_name = QStandardPaths::locate (QStandardPaths::AppConfigLocation
, "hamlib_settings.json");
if (!settings_file_name.isEmpty ())
{
QFile settings_file {settings_file_name};
qDebug () << "Using Hamlib settings file:" << settings_file_name;
if (settings_file.open (QFile::ReadOnly))
{
QJsonParseError status;
auto settings_doc = QJsonDocument::fromJson (settings_file.readAll (), &status);
if (status.error)
{
throw error {tr ("Hamlib settings file error: %1 at character offset %2")
.arg (status.errorString ()).arg (status.offset)};
}
qDebug () << "Hamlib settings JSON:" << settings_doc.toJson ();
if (!settings_doc.isObject ())
{
throw error {tr ("Hamlib settings file error: top level must be a JSON object")};
}
auto const& settings = settings_doc.object ();
//
// configuration settings
//
auto const& config = settings["config"];
if (!config.isUndefined ())
{
if (!config.isObject ())
{
throw error {tr ("Hamlib settings file error: config must be a JSON object")};
}
auto const& config_list = config.toObject ();
for (auto item = config_list.constBegin (); item != config_list.constEnd (); ++item)
{
set_conf (item.key ().toLocal8Bit ().constData ()
, (*item).toVariant ().toString ().toLocal8Bit ().constData ());
}
}
}
}
}
int HamlibTransceiver::do_start () int HamlibTransceiver::do_start ()
{ {
CAT_TRACE ("starting: " << rig_get_caps_cptr (m_->model_, RIG_CAPS_MFG_NAME_CPTR) CAT_TRACE ("starting: " << rig_get_caps_cptr (m_->model_, RIG_CAPS_MFG_NAME_CPTR)

View File

@ -24,6 +24,7 @@ public:
~HamlibTransceiver (); ~HamlibTransceiver ();
private: private:
void load_user_settings ();
int do_start () override; int do_start () override;
void do_stop () override; void do_stop () override;
void do_frequency (Frequency, MODE, bool no_ignore) override; void do_frequency (Frequency, MODE, bool no_ignore) override;

View File

@ -192,7 +192,7 @@ WSJTXLogging::WSJTXLogging ()
( (
sinks::file::make_collector sinks::file::make_collector
( (
keywords::max_size = 40 * 1024 * 1024 keywords::max_size = 5 * 1024 * 1024
, keywords::min_free_space = 1024 * 1024 * 1024 , keywords::min_free_space = 1024 * 1024 * 1024
, keywords::max_files = 12 , keywords::max_files = 12
, keywords::target = app_data.absoluteFilePath ("logs").toStdWString () , keywords::target = app_data.absoluteFilePath ("logs").toStdWString ()

842
cty.dat

File diff suppressed because it is too large Load Diff

View File

@ -166,9 +166,9 @@ function (document)
COMMAND ${ASCIIDOCTOR_EXECUTABLE} ${_args_ASCIIDOCTOR_OPTIONS} COMMAND ${ASCIIDOCTOR_EXECUTABLE} ${_args_ASCIIDOCTOR_OPTIONS}
-b html5 -b html5
-a nofooter -a nofooter
-a VERSION_MAJOR=${WSJTX_VERSION_MAJOR} -a VERSION_MAJOR=${PROJECT_VERSION_MAJOR}
-a VERSION_MINOR=${WSJTX_VERSION_MINOR} -a VERSION_MINOR=${PROJECT_VERSION_MINOR}
-a VERSION_PATCH=${WSJTX_VERSION_PATCH} -a VERSION_PATCH=${PROJECT_VERSION_PATCH}
-a VERSION=${wsjtx_VERSION} -a VERSION=${wsjtx_VERSION}
--out-file=${_html_file} ${_source_name} --out-file=${_html_file} ${_source_name}
DEPENDS ${_args_DEPENDS} DEPENDS ${_args_DEPENDS}
@ -195,9 +195,9 @@ function (document)
COMMAND ${ASCIIDOCTOR_EXECUTABLE} ARGS ${_args_ASCIIDOCTOR_OPTIONS} COMMAND ${ASCIIDOCTOR_EXECUTABLE} ARGS ${_args_ASCIIDOCTOR_OPTIONS}
-b docbook -b docbook
-a data-uri! -a data-uri!
-a VERSION_MAJOR=${WSJTX_VERSION_MAJOR} -a VERSION_MAJOR=${wsjtx_VERSION_MAJOR}
-a VERSION_MINOR=${WSJTX_VERSION_MINOR} -a VERSION_MINOR=${wsjtx_VERSION_MINOR}
-a VERSION_PATCH=${WSJTX_VERSION_PATCH}${BUILD_TYPE_REVISION} -a VERSION_PATCH=${wsjtx_VERSION_PATCH}${BUILD_TYPE_REVISION}
-a VERSION=${wsjtx_VERSION} -a VERSION=${wsjtx_VERSION}
-D ${CMAKE_CURRENT_BINARY_DIR} -D ${CMAKE_CURRENT_BINARY_DIR}
-o ${_docbook_file} ${_source_name} -o ${_docbook_file} ${_source_name}

View File

@ -94,8 +94,8 @@ d). Edit lines as needed. Keeping them in alphabetic order help see dupes.
:sourceforge-jtsdk: https://sourceforge.net/projects/jtsdk[SourceForge JTSDK] :sourceforge-jtsdk: https://sourceforge.net/projects/jtsdk[SourceForge JTSDK]
:ubuntu_sdk: https://launchpad.net/~ubuntu-sdk-team/+archive/ppa[Ubuntu SDK Notice] :ubuntu_sdk: https://launchpad.net/~ubuntu-sdk-team/+archive/ppa[Ubuntu SDK Notice]
:win_openssl_packages: https://slproweb.com/products/Win32OpenSSL.html[Windows OpenSSL Packages] :win_openssl_packages: https://slproweb.com/products/Win32OpenSSL.html[Windows OpenSSL Packages]
:win32_openssl: https://slproweb.com/download/Win32OpenSSL_Light-1_1_1h.msi[Win32 OpenSSL Light Package] :win32_openssl: https://slproweb.com/download/Win32OpenSSL_Light-1_1_1j.msi[Win32 OpenSSL Light Package]
:win64_openssl: https://slproweb.com/download/Win64OpenSSL_Light-1_1_1h.msi[Win64 OpenSSL Light Package] :win64_openssl: https://slproweb.com/download/Win64OpenSSL_Light-1_1_1j.msi[Win64 OpenSSL Light Package]
:writelog: https://writelog.com/[Writelog] :writelog: https://writelog.com/[Writelog]
:wsjtx_group: https://groups.io/g/WSJTX[WSJTX Group] :wsjtx_group: https://groups.io/g/WSJTX[WSJTX Group]
:wsjtx: https://physics.princeton.edu/pulsar/K1JT/wsjtx.html[WSJT-X] :wsjtx: https://physics.princeton.edu/pulsar/K1JT/wsjtx.html[WSJT-X]

View File

@ -37,6 +37,12 @@ examples for configurations `FT8` and `Echo`:
==== View Menu ==== View Menu
image::view-menu.png[align="left",alt="View Menu"] image::view-menu.png[align="left",alt="View Menu"]
The *SWL Mode* action reduces the _WSJT-X_ main window to a minimum
size with just the menus, decodes windows, and status bar visible. You
may find this useful when running multiple instances of the
application. Both size and location of the main window are saved and
recalled independently for this view.
[[MODE_MENU]] [[MODE_MENU]]
==== Mode Menu ==== Mode Menu
image::mode-menu.png[align="left",alt="Mode Menu"] image::mode-menu.png[align="left",alt="Mode Menu"]

View File

@ -1,11 +1,10 @@
// Status=edited // Status=edited
Two arrangements of controls are provided for generating and selecting Controls familiar to users of program _WSJT_ appear on *Tab 1*,
Tx messages. Controls familiar to users of program _WSJT_ providing six fields for message entry. Pre-formatted messages for
appear on *Tab 1*, providing six fields for message entry. the standard minimal QSO are generated when you click *Generate Std
Pre-formatted messages for the standard minimal QSO are generated when Msgs* or double-click on an appropriate line in one of the decoded
you click *Generate Std Msgs* or double-click on an appropriate line text windows.
in one of the decoded text windows.
//.Traditional Message Menu //.Traditional Message Menu
image::traditional-msg-box.png[align="center",alt="Traditional Message Menu"] image::traditional-msg-box.png[align="center",alt="Traditional Message Menu"]
@ -28,31 +27,12 @@ stored messages entered on the *Files -> Settings -> Tx Macros* tab.
Pressing *Enter* on a modified message #5 automatically adds that Pressing *Enter* on a modified message #5 automatically adds that
message to the stored macros. message to the stored macros.
* In some circumstances it may be desirable to make your QSOs as * In some circumstances it may be desirable to make your QSOs as short
short as possible. To configure the program to start contacts with as possible. To configure the program to start contacts with message
message #2, disable message #1 by double-clicking its radio-button in the *Next* column or *Tx 1* button in the *Now* column. Similarly, to send RR73 #2, disable message #1 by double-clicking its radio-button in the
rather than RRR for message #4, double-click one of its buttons. *Next* column or *Tx 1* button in the *Now* column. Similarly, to
send RR73 rather than RRR for message #4, double-click one of its
The second arrangement of controls for generating and selecting buttons.
Tx messages appears on *Tab 2* of the Message Control Panel:
//.New Message Menu
image::new-msg-box.png[align="center",alt="New Message Menu"]
With this setup you normally follow a top-to-bottom sequence of
transmissions from the left column if you are calling CQ, or the right
column if answering a CQ.
* Clicking a button puts the appropriate message in the *Gen Msg* box.
If you are already transmitting, the Tx message is changed
immediately.
* You can enter and transmit anything (up to 13 characters, including
spaces) in the *Free Msg* box.
* Click the pull-down arrow in the *Free Msg* box to select a
stored macro. Pressing *Enter* on a modified message here
automatically adds that message to the table of stored macros.
+ +

View File

@ -2,12 +2,12 @@
=== AP Decoding === AP Decoding
The _WSJT-X_ decoders for FT4, FT8, JT65, QRA64, include The _WSJT-X_ decoders for FST4, FT4, FT8, JT65, and QRA64 include
procedures that use naturally accumulating information during a procedures that use naturally accumulating information during a
minimal QSO. This _a priori_ (AP) information increases sensitivity minimal QSO. This _a priori_ (AP) information increases sensitivity
of the decoder by up to 4 dB, at the cost of a slightly higher rate of of the decoder by up to 4 dB, at the cost of a slightly higher rate of
false decodes. AP is optional in FT8, JT65, and QRA64, but is always false decodes. AP is optional in FT8, JT65, and QRA64, but is always
enabled for FT4. enabled for FT4 and FST4 when decode depth is Normal or Deep.
For example: when you decide to answer a CQ, you already know your own For example: when you decide to answer a CQ, you already know your own
callsign and that of your potential QSO partner. The software callsign and that of your potential QSO partner. The software
@ -27,7 +27,7 @@ example, `a2` indicates that the successful decode used MyCall as
hypothetically known information. hypothetically known information.
[[FT8_AP_INFO_TABLE]] [[FT8_AP_INFO_TABLE]]
.FT4 and FT8 AP information types .FST4, FT4, and FT8 AP information types
[width="35%",cols="h10,<m20",frame=topbot,options="header"] [width="35%",cols="h10,<m20",frame=topbot,options="header"]
|=============================================== |===============================================
|aP | Message components |aP | Message components
@ -47,7 +47,9 @@ forwarded to {pskreporter}.
Table 2 lists the six possible QSO states that are tracked by the Table 2 lists the six possible QSO states that are tracked by the
_WSJT-X_ auto-sequencer, along with the type of AP decoding that would _WSJT-X_ auto-sequencer, along with the type of AP decoding that would
be attempted in each state. be attempted in each state in FT4 or FT8. The FST4 table (not shown)
is the same except that it omits the decoding attempts for AP types
4 and 5 to save time.
[[FT8_AP_DECODING_TYPES_TABLE]] [[FT8_AP_DECODING_TYPES_TABLE]]
.FT4 and FT8 AP decoding types for each QSO state .FT4 and FT8 AP decoding types for each QSO state
@ -109,13 +111,15 @@ summarized in the following Table:
[width="50%",cols="h,3*^",frame=topbot,options="header"] [width="50%",cols="h,3*^",frame=topbot,options="header"]
|=========================================== |===========================================
|Mode |Mode character|Sync character|End of line information |Mode |Mode character|Sync character|End of line information
|FST4 | ` | | ? &#160; aP
|FT4 | ~ | | ? &#160; aP |FT4 | ~ | | ? &#160; aP
|FT8 | ~ | | ? &#160; aP |FT8 | ~ | | ? &#160; aP
|JT4 | $ | *, # | f, fN, dCN |JT4 | $ | *, # | f, fN, dCN
|JT9 | @ | | |JT9 | @ | |
|JT65 | # | | |JT65 | # | |
|JT65 VHF| # | *, # | f, fN, dCN |JT65 VHF| # | *, # | f, fN, dCN
|QRA64 | : | * | R |QRA64 | : | * | R:w
|ISCAT | | * | M N C T |ISCAT | | * | M N C T
|MSK144 | & | | |MSK144 | & | |
|=========================================== |===========================================

Binary file not shown.

Before

Width:  |  Height:  |  Size: 230 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 389 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -160,7 +160,7 @@ guidelines for contest logging with FT4, FT8, and MSK144:
[[COMP-CALL]] [[COMP-CALL]]
=== Nonstandard Callsigns === Nonstandard Callsigns
*FT4, FT8, and MSK144* *FT4, FT8, FST4, and MSK144*
Compound callsigns like xx/K1ABC or K1ABC/x and special event Compound callsigns like xx/K1ABC or K1ABC/x and special event
callsigns like YW18FIFA are supported for normal QSOs but not for callsigns like YW18FIFA are supported for normal QSOs but not for

View File

@ -31,4 +31,9 @@ synchronization symbols.
for making 2-way QSOs, and FST4W should replace WSPR for propagation for making 2-way QSOs, and FST4W should replace WSPR for propagation
tests*. Operating conventions on these LF and MF bands will tests*. Operating conventions on these LF and MF bands will
eventually determine the most useful T/R sequence lengths for each eventually determine the most useful T/R sequence lengths for each
type of operation. type of operation. We also expect that the 60 second variant of FST4
(FST4-60) will outperform JT9 for DX QSOs on HF bands due, in part,
to the FST4 decoder's ability to use AP decoding for messages received
from a QSO partner. In addition, FST4 provides the added benefits
associated with 77-bit messages and auto-sequencing.

View File

@ -18,6 +18,13 @@ image::colors.png[align="center",alt="Colors Screen"]
* Check *Highlight by Mode* if you wish worked before status to be per * Check *Highlight by Mode* if you wish worked before status to be per
<<INTRO,mode>>. <<INTRO,mode>>.
* Check *Only grid Fields sought* if you are only interested in the
leading two character grid locator Fields rather than teh four
character grid locator Squares.
* Check *Include extra WAE entities* if you are interested in the
extra entities defined for DARC WAE and CQ Marathon awards.
* Worked before status is calculated from your _WSJT-X_ ADIF * Worked before status is calculated from your _WSJT-X_ ADIF
<<LOGGING, Logging>> file, you may replace ADIF log file with one <<LOGGING, Logging>> file, you may replace ADIF log file with one
exported from your station logging application, *Rescan ADIF Log* exported from your station logging application, *Rescan ADIF Log*

View File

@ -96,5 +96,6 @@ green to indicate that proper communication has been established.
Failure of the CAT-control test turns the button red and displays an Failure of the CAT-control test turns the button red and displays an
error message. After a successful CAT test, toggle the *Test PTT* error message. After a successful CAT test, toggle the *Test PTT*
button to confirm that your selected method of T/R control is working button to confirm that your selected method of T/R control is working
properly. (If you selected *VOX* for _PTT Method_, you can test T/R properly, the button turns red if the rig has been successfully
keyed. (If you selected *VOX* for _PTT Method_, you can test T/R
switching later by using the *Tune* button on the main window.) switching later by using the *Tune* button on the main window.)

View File

@ -19,6 +19,10 @@ QRZ messages. Full details of the protocol can be found in comments
at the top of this file in our source code repository: at the top of this file in our source code repository:
https://sourceforge.net/p/wsjt/wsjtx/ci/master/tree/Network/NetworkMessage.hpp https://sourceforge.net/p/wsjt/wsjtx/ci/master/tree/Network/NetworkMessage.hpp
NOTE: The *Outgoing interfaces* and *Multicast TTL* fields are only
present when a multicast group IP address has been entered in
the *UDP Server* field.
Programs like _JTAlert_ use the _UDP Server_ feature to obtain Programs like _JTAlert_ use the _UDP Server_ feature to obtain
information about running _WSJT-X_ instances. If you are using information about running _WSJT-X_ instances. If you are using
_JTAlert_ to control _WSJT-X_, be sure to check the _JTAlert_ to control _WSJT-X_, be sure to check the

View File

@ -16,6 +16,5 @@ characters) in the entry field at top, then click *Add*.
- You can reorder your macro messages by using drag-and-drop. The - You can reorder your macro messages by using drag-and-drop. The
new order will be preserved when _WSJT-X_ is restarted. new order will be preserved when _WSJT-X_ is restarted.
- Messages can also be added from the main window's *Tx5* field on Tab - Messages can also be added from the main window's *Tx5*
1 or the *Free msg* field on Tab 2. Simply hit [Enter] after the field. Simply hit [Enter] after the message has been entered.
message has been entered.

View File

@ -1,5 +1,19 @@
Do not confuse FST4 with FT4, which has a very different purpose! Do not confuse FST4 with FT4, which has a very different purpose!
FST4 is is designed for making 2-way QSOs on the LF and MF bands. FST4 is designed primarily for making weak-signal 2-way QSOs on the
LF and MF bands. T/R periods from 15 s up to 1800 s are
available. Longer T/R periods provide better sensitivity only if
Tx and Rx frequency instability and channel Doppler spread
are small enough so that received signals
remain phase coherent over periods spanning several transmitted symbols.
Generally speaking, Rx and Tx frequency changes
during the transmission and channel Doppler spread should each be small compared
to the symbol keying rate shown for each T/R duration in Table 7 within section
<<PROTOCOL_OVERVIEW,Protocol Specifications>>. For example, the keying rate for
the 1800 s T/R period is 0.089 Baud, so
successful operation using this T/R length requires Tx and Rx frequency
stability better than 0.089 Hz over the duration of the 1800 s transmission in
addition to channel Doppler spread smaller than 0.089 Hz.
Operation with FST4 is similar to that with other _WSJT-X_ modes: most Operation with FST4 is similar to that with other _WSJT-X_ modes: most
on-screen controls, auto-sequencing, and other features behave in on-screen controls, auto-sequencing, and other features behave in
familiar ways. However, operating conventions on the 2200 and 630 m familiar ways. However, operating conventions on the 2200 and 630 m
@ -21,3 +35,26 @@ decoding process (and of course will be undecodable). By checking
further limit the decoding range to the setting of *F Tol* on further limit the decoding range to the setting of *F Tol* on
either side of *Rx Freq*. either side of *Rx Freq*.
A noise blanker can be enabled by setting the *NB* percentage to a non-zero value.
This setting determines how many of the largest-amplitude samples will be
blanked (zeroed) before the data is submitted to the decoder. Most users find
that settings between 0% (no blanking) and 10% work best. If the noise
blanker percentage is set to -1%, then the decoder will try 0, 5, 10, 15, and 20 %
in succession. Similarly, a setting of -2% causes the decoder to loop over
blanking percentages 0, 2, 4, ... 20 %. To save time, the multiple blanking
percentages triggered by negative *NB* settings are tried only for signal
candidates located near (within +/- 20 Hz) of the *Rx* frequency setting.
.Open a sample Wave File:
- Select *FST4* on the *Mode* menu. Set *T/R* to 60 s and *Decode | Deep*.
- Set *NB* (noise blanker) to 0%.
- Set up the Wide Graph display with settings appropriate for the FST4-60 mode.
For example, try *Bins/Pixel* 2 and *N Avg* 4. Set the *Start* frequency and the width of
the Wide Graph to include the frequency range that you want to decode. For this
example, make sure that *Start* is less than 1000 Hz and that the Wide Graph extends to above 1400 Hz.
- Set *F Low* 1000, *F High* 1400. These settings define the decoder's frequency search range.
- Open a sample Wave file using *File | Open* and select the file
...\save\samples\FST4+FST4W\210115_0058.wav. After _WSJT-X_ has processed the file you should see something similar to the following screen shot:
image::FST4-1.png[align="left"]

View File

@ -1,5 +1,5 @@
FST4W is used in the same way as WSPR, but FST4W has significant FST4W is used in the same way as WSPR, but FST4W has significant
advantages for use on the 2200 and 630 m bands. By default the advantages for use on the 2200 m and 630 m bands. By default the
central *Rx Freq* is 1500 Hz and *F Tol* is 100 Hz, so the active central *Rx Freq* is 1500 Hz and *F Tol* is 100 Hz, so the active
decoding range is 1400 to 1600 Hz. However, for added flexibility you decoding range is 1400 to 1600 Hz. However, for added flexibility you
can select different center frequencies and *F Tol* values. We expect can select different center frequencies and *F Tol* values. We expect
@ -16,3 +16,19 @@ If three operators agree in advance to select the options *1/3*,
a fixed sequence with no two stations transmitting simultaneously. a fixed sequence with no two stations transmitting simultaneously.
Sequence 1 is the first sequence after 00:00 UTC. For WSPR-like Sequence 1 is the first sequence after 00:00 UTC. For WSPR-like
scheduling behavior, you should select *Random* with this control. scheduling behavior, you should select *Random* with this control.
.Open a Wave File:
- Select *FST4W* on the *Mode* menu. Set *T/R* to 1800 s and *Decode | Deep*.
- Set *NB* to 0%.
- Select appropriate wide graph settings. For example, try *Bins/Pixel* 1,
*Start* 1200 Hz and *N Avg* 150.
- Open a sample Wave file using *File | Open* and select the file
...\save\samples\FST4+FST4W\201230_0300.wav.
When it is finished you should see a single decode as shown in the
screenshot:
image::FST4W-1.png[align="left"]
Note that the weak signal associated with the single decode is all but invisible on the
widegraph spectrogram.

View File

@ -13,9 +13,6 @@ and *Page Up/Down* key presses, with the *Page* keys moving the
controls in larger steps. You can also type numbers directly into controls in larger steps. You can also type numbers directly into
the spinner controls or use the mouse wheel. the spinner controls or use the mouse wheel.
- Select *Tab 2* (below the *Decode* button) to choose the alternative
set of controls for generating and selecting Tx messages.
[[DOWNLOAD_SAMPLES]] [[DOWNLOAD_SAMPLES]]
=== Download Samples === Download Samples

View File

@ -381,7 +381,7 @@ decode*, *Decode after EME delay*
.Wide Graph: .Wide Graph:
- *Bins/Pixel* = 3, *N Avg* = 10 - *Bins/Pixel* = 4, *N Avg* = 10
- Adjust the width of the window so that the frequency range extends - Adjust the width of the window so that the frequency range extends
up to at least 2400 Hz. up to at least 2400 Hz.

View File

@ -119,6 +119,15 @@ In macOS, enter the following command from a terminal:
open /Applications/wsjtx.app --args -stylesheet :/qdarkstyle/style.qss open /Applications/wsjtx.app --args -stylesheet :/qdarkstyle/style.qss
In Linux using the Unity or GNOME GUI the following commands will
update the _WSJT-X_ start up:
....
sed '/Exec=wsjtx/ s/$/ -stylesheet :\/qdarkstyle\/style.qss/' \
/usr/share/applications/wsjtx.desktop >~/.local/share/applications/wsjtx.desktop
update-desktop-database ~/.local/share/applications/
....
Depending on your operating system, the main _WSJT-X_ window will look Depending on your operating system, the main _WSJT-X_ window will look
something like this: something like this:
@ -193,7 +202,7 @@ include::wspr.adoc[]
include::controls-functions-menus.adoc[] include::controls-functions-menus.adoc[]
[[CONTROLS_MAIN]] [[CONTROLS_MAIN]]
=== Button Row === Button Row
include::controls-functions-main-window.adoc[] include::controls-functions-main-window.adoc[]
[[CONTROLS_LEFT]] [[CONTROLS_LEFT]]

View File

@ -7,7 +7,7 @@ TargetFileName="${AppLocalDataLocation}/logs/wsjtx_syslog_%Y-%m.log"
RotationTimePoint="01 00:00:00" RotationTimePoint="01 00:00:00"
Append=true Append=true
EnableFinalRotation=false EnableFinalRotation=false
MaxSize=41943040 MaxSize=52428800
MinFreeSpace=1073741824 MinFreeSpace=1073741824
MaxFiles=12 MaxFiles=12
Target="${AppLocalDataLocation}/logs" Target="${AppLocalDataLocation}/logs"

View File

@ -614,7 +614,7 @@ contains
endif endif
call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, & call this%callback(nutc,smax1,nsnr,xdt,fsig,msg, &
iaptype,qual,ntrperiod,lwspr,fmid,w50) iaptype,qual,ntrperiod,lwspr,fmid,w50)
if(iwspr.eq.0 .and. nb.lt.0) go to 900 ! if(iwspr.eq.0 .and. nb.lt.0) go to 900
goto 800 goto 800
endif endif
enddo ! metrics enddo ! metrics

View File

@ -65,7 +65,8 @@ program ft4code
if(i3.eq.2) msgtype="EU VHF Contest" if(i3.eq.2) msgtype="EU VHF Contest"
if(i3.eq.3) msgtype="ARRL RTTY Roundup" if(i3.eq.3) msgtype="ARRL RTTY Roundup"
if(i3.eq.4) msgtype="Nonstandard calls" if(i3.eq.4) msgtype="Nonstandard calls"
if(i3.ge.5) msgtype="Undefined msg type" if(i3.eq.5) msgtype="EU VHF Contest"
if(i3.ge.6) msgtype="Undefined msg type"
if(i3.ge.1) n3=-1 if(i3.ge.1) n3=-1
bad=" " bad=" "
comment=' ' comment=' '

View File

@ -64,7 +64,8 @@ program ft8code
if(i3.eq.2) msgtype="EU VHF Contest" if(i3.eq.2) msgtype="EU VHF Contest"
if(i3.eq.3) msgtype="ARRL RTTY Roundup" if(i3.eq.3) msgtype="ARRL RTTY Roundup"
if(i3.eq.4) msgtype="Nonstandard call" if(i3.eq.4) msgtype="Nonstandard call"
if(i3.ge.5) msgtype="Undefined type" if(i3.eq.5) msgtype="EU VHF Contest"
if(i3.ge.6) msgtype="Undefined type"
if(i3.ge.1) n3=-1 if(i3.ge.1) n3=-1
bad=" " bad=" "
comment=' ' comment=' '

View File

@ -51,7 +51,8 @@ program msk144code
if(i3.eq.2) msgtype="EU VHF Contest" if(i3.eq.2) msgtype="EU VHF Contest"
if(i3.eq.3) msgtype="ARRL RTTY Roundup" if(i3.eq.3) msgtype="ARRL RTTY Roundup"
if(i3.eq.4) msgtype="Nonstandard calls" if(i3.eq.4) msgtype="Nonstandard calls"
if(i3.ge.5) msgtype="Undefined msg type" if(i3.eq.5) msgtype="EU VHF Contest"
if(i3.ge.6) msgtype="Undefined msg type"
if(i3.ge.1) n3=-1 if(i3.ge.1) n3=-1
if(i4tone(41).lt.0) then if(i4tone(41).lt.0) then
msgtype="Sh msg" msgtype="Sh msg"

View File

@ -100,7 +100,7 @@ subroutine msk144decodeframe(c,softbits,msgreceived,nsuccess)
nsuccess=1 nsuccess=1
write(c77,'(77i1)') decoded77 write(c77,'(77i1)') decoded77
read(c77(72:77),'(2b3)') n3,i3 read(c77(72:77),'(2b3)') n3,i3
if( (i3.eq.0.and.(n3.eq.1 .or. n3.eq.3 .or. n3.eq.4 .or. n3.gt.5)) .or. i3.eq.3 .or. i3.gt.4 ) then if( (i3.eq.0.and.(n3.eq.1 .or. n3.eq.3 .or. n3.eq.4 .or. n3.gt.5)) .or. i3.eq.3 .or. i3.gt.5 ) then
nsuccess=0 nsuccess=0
else else
call unpack77(c77,1,msgreceived,unpk77_success) call unpack77(c77,1,msgreceived,unpk77_success)

View File

@ -225,8 +225,7 @@ int main(int argc, char *argv[])
// disallow multiple instances with same instance key // disallow multiple instances with same instance key
QLockFile instance_lock {temp_dir.absoluteFilePath (a.applicationName () + ".lock")}; QLockFile instance_lock {temp_dir.absoluteFilePath (a.applicationName () + ".lock")};
instance_lock.setStaleLockTime (0); instance_lock.setStaleLockTime (0);
bool lock_ok {false}; while (!instance_lock.tryLock ())
while (!(lock_ok = instance_lock.tryLock ()))
{ {
if (QLockFile::LockFailedError == instance_lock.error ()) if (QLockFile::LockFailedError == instance_lock.error ())
{ {
@ -249,6 +248,10 @@ int main(int argc, char *argv[])
throw std::runtime_error {"Multiple instances must have unique rig names"}; throw std::runtime_error {"Multiple instances must have unique rig names"};
} }
} }
else
{
throw std::runtime_error {"Failed to access lock file"};
}
} }
// load UI translations // load UI translations

View File

@ -1,6 +1,10 @@
set (SAMPLE_FILES set (SAMPLE_FILES
FT4/000000_000002.wav FT4/000000_000002.wav
FT8/181201_180245.wav FT8/181201_180245.wav
FST4+FST4W/210115_0058.wav
FST4+FST4W/201230_0300.wav
MSK144/181211_120500.wav
MSK144/181211_120800.wav
ISCAT/ISCAT-A/VK7MO_110401_235515.wav ISCAT/ISCAT-A/VK7MO_110401_235515.wav
ISCAT/ISCAT-B/K0AWU_100714_115000.wav ISCAT/ISCAT-B/K0AWU_100714_115000.wav
JT4/JT4A/DF2ZC_070926_040700.WAV JT4/JT4A/DF2ZC_070926_040700.WAV
@ -17,6 +21,7 @@ set (SAMPLE_FILES
JT9/130418_1742.wav JT9/130418_1742.wav
MSK144/181211_120500.wav MSK144/181211_120500.wav
MSK144/181211_120800.wav MSK144/181211_120800.wav
QRA64/QRA64C/161113_0111.wav
WSPR/150426_0918.wav WSPR/150426_0918.wav
Q65/30A_Ionoscatter_6m/201203_022700.wav Q65/30A_Ionoscatter_6m/201203_022700.wav
Q65/30A_Ionoscatter_6m/201203_022800.wav Q65/30A_Ionoscatter_6m/201203_022800.wav

Binary file not shown.

Binary file not shown.

View File

@ -64,7 +64,10 @@ void AbstractLogWindow::impl::delete_QSOs ()
, tr ("Confirm Delete") , tr ("Confirm Delete")
, tr ("Are you sure you want to delete the %n " , tr ("Are you sure you want to delete the %n "
"selected QSO(s) from the log?", "" "selected QSO(s) from the log?", ""
, row_indexes.size ()))) , row_indexes.size ())
, QString {}
, MessageBox::Yes | MessageBox::No
, MessageBox::No))
{ {
// We must work with source model indexes because we don't want row // We must work with source model indexes because we don't want row
// removes to invalidate model indexes we haven't yet processed. We // removes to invalidate model indexes we haven't yet processed. We

View File

@ -3633,7 +3633,7 @@ void MainWindow::auto_sequence (DecodedText const& message, unsigned start_toler
auto const& message_words = message.messageWords (); auto const& message_words = message.messageWords ();
auto is_73 = message_words.filter (QRegularExpression {"^(73|RR73)$"}).size(); auto is_73 = message_words.filter (QRegularExpression {"^(73|RR73)$"}).size();
bool is_OK=false; bool is_OK=false;
if(m_mode=="MSK144" and message.string().indexOf(ui->dxCallEntry->text()+" R ")>0) is_OK=true; if(m_mode=="MSK144" and message.clean_string ().indexOf(ui->dxCallEntry->text()+" R ")>0) is_OK=true;
if (message_words.size () > 2 && (message.isStandardMessage() || (is_73 or is_OK))) { if (message_words.size () > 2 && (message.isStandardMessage() || (is_73 or is_OK))) {
auto df = message.frequencyOffset (); auto df = message.frequencyOffset ();
auto within_tolerance = (qAbs (ui->RxFreqSpinBox->value () - df) <= int (start_tolerance) auto within_tolerance = (qAbs (ui->RxFreqSpinBox->value () - df) <= int (start_tolerance)
@ -3648,7 +3648,7 @@ void MainWindow::auto_sequence (DecodedText const& message, unsigned start_toler
|| message_words.contains ("DE"))) || message_words.contains ("DE")))
|| !message.isStandardMessage ()); // free text 73/RR73 || !message.isStandardMessage ()); // free text 73/RR73
QStringList w=message.string().mid(22).remove("<").remove(">").split(" ",SkipEmptyParts); QStringList w=message.clean_string ().mid(22).remove("<").remove(">").split(" ",SkipEmptyParts);
QString w2; QString w2;
int nrpt=0; int nrpt=0;
if (w.size () > 2) if (w.size () > 2)
@ -3660,8 +3660,8 @@ void MainWindow::auto_sequence (DecodedText const& message, unsigned start_toler
} }
} }
bool bEU_VHF=(nrpt>=520001 and nrpt<=594000); bool bEU_VHF=(nrpt>=520001 and nrpt<=594000);
if(bEU_VHF and message.string().contains("<"+m_config.my_callsign() + "> ")) { if(bEU_VHF and message.clean_string ().contains("<"+m_config.my_callsign() + "> ")) {
m_xRcvd=message.string().trimmed().right(13); m_xRcvd=message.clean_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))
@ -4180,7 +4180,7 @@ void MainWindow::guiUpdate()
statusUpdate (); statusUpdate ();
} }
} }
m_bCallingCQ = CALLING == m_QSOProgress m_bCallingCQ = 6 == m_ntx
|| m_currentMessage.contains (QRegularExpression {"^(CQ|QRZ) "}); || m_currentMessage.contains (QRegularExpression {"^(CQ|QRZ) "});
if(m_mode=="FT8" or m_mode=="FT4") { if(m_mode=="FT8" or m_mode=="FT4") {
if(m_bCallingCQ && ui->cbFirst->isVisible () && ui->cbFirst->isChecked ()) { if(m_bCallingCQ && ui->cbFirst->isVisible () && ui->cbFirst->isChecked ()) {
@ -4212,16 +4212,15 @@ void MainWindow::guiUpdate()
msg_parts[1].remove (QChar {'<'}); msg_parts[1].remove (QChar {'<'});
msg_parts[1].remove (QChar {'>'}); msg_parts[1].remove (QChar {'>'});
} }
auto is_73 = m_QSOProgress >= ROGER_REPORT auto is_73 = message_is_73 (m_currentMessageType, msg_parts);
&& message_is_73 (m_currentMessageType, msg_parts);
m_sentFirst73 = is_73 m_sentFirst73 = is_73
&& !message_is_73 (m_lastMessageType, m_lastMessageSent.split (' ', SkipEmptyParts)); && !message_is_73 (m_lastMessageType, m_lastMessageSent.split (' ', SkipEmptyParts));
if (m_sentFirst73) { if (m_sentFirst73 || (is_73 && CALLING == m_QSOProgress)) {
m_qsoStop=t2; m_qsoStop=t2;
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) logQSOTimer.start(0); if((m_config.prompt_to_log() or m_config.autoLog()) && !m_tune && CALLING != m_QSOProgress) logQSOTimer.start(0);
} }
bool b=(m_mode=="FT8" or m_mode=="FT4") and ui->cbAutoSeq->isChecked(); bool b=(m_mode=="FT8" or m_mode=="FT4") and ui->cbAutoSeq->isChecked();
@ -4778,7 +4777,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
auto ctrl = modifiers.testFlag (Qt::ControlModifier); auto ctrl = modifiers.testFlag (Qt::ControlModifier);
// auto alt = modifiers.testFlag (Qt::AltModifier); // auto alt = modifiers.testFlag (Qt::AltModifier);
// basic mode sanity checks // basic mode sanity checks
auto const& parts = message.string ().split (' ', SkipEmptyParts); auto const& parts = message.clean_string ().split (' ', SkipEmptyParts);
if (parts.size () < 5) return; if (parts.size () < 5) return;
auto const& mode = parts.at (4).left (1); auto const& mode = parts.at (4).left (1);
if (("JT65" == m_mode && mode != "#") if (("JT65" == m_mode && mode != "#")
@ -4827,16 +4826,16 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
QString hisgrid; QString hisgrid;
message.deCallAndGrid(/*out*/hiscall,hisgrid); message.deCallAndGrid(/*out*/hiscall,hisgrid);
if(message.string().contains(hiscall+"/R")) { if(message.clean_string ().contains(hiscall+"/R")) {
hiscall+="/R"; hiscall+="/R";
ui->dxCallEntry->setText(hiscall); ui->dxCallEntry->setText(hiscall);
} }
if(message.string().contains(hiscall+"/P")) { if(message.clean_string ().contains(hiscall+"/P")) {
hiscall+="/P"; hiscall+="/P";
ui->dxCallEntry->setText(hiscall); ui->dxCallEntry->setText(hiscall);
} }
QStringList w=message.string().mid(22).remove("<").remove(">").split(" ",SkipEmptyParts); QStringList w=message.clean_string ().mid(22).remove("<").remove(">").split(" ",SkipEmptyParts);
int nw=w.size(); int nw=w.size();
if(nw>=4) { if(nw>=4) {
if(message_words.size()<3) return; if(message_words.size()<3) return;
@ -4848,9 +4847,9 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
} }
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.clean_string ().contains("<")) {
qDebug () << "Not processing message - hiscall:" << hiscall << "hisgrid:" << hisgrid qDebug () << "Not processing message - hiscall:" << hiscall << "hisgrid:" << hisgrid
<< message.string() << message.isStandardMessage(); << message.clean_string () << message.isStandardMessage();
return; return;
} }
@ -4892,7 +4891,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
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
auto dtext = " " + message.string () + " "; auto dtext = " " + message.clean_string () + " ";
dtext=dtext.remove("<").remove(">"); dtext=dtext.remove("<").remove(">");
if(dtext.contains (" " + m_baseCall + " ") if(dtext.contains (" " + m_baseCall + " ")
|| dtext.contains ("<" + m_baseCall + "> ") || dtext.contains ("<" + m_baseCall + "> ")
@ -4920,7 +4919,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
MessageBox::information_message (this, msg); MessageBox::information_message (this, msg);
} }
QStringList t=message.string().split(' ', SkipEmptyParts); QStringList t=message.clean_string ().split(' ', SkipEmptyParts);
int n=t.size(); int n=t.size();
QString t0=t.at(n-2); QString t0=t.at(n-2);
QString t1=t0.right(1); QString t1=t0.right(1);
@ -4996,11 +4995,11 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
} }
} else { // no grid on end of msg } else { // no grid on end of msg
auto const& word_3 = message_words.at (3); auto const& word_3 = message_words.at (3);
bool word_3_is_int; auto word_3_as_number = word_3.toInt ();
auto word_3_as_number = word_3.toInt (&word_3_is_int); if (("RRR" == word_3
if(m_QSOProgress >= ROGER_REPORT && ("RRR" == word_3 || word_3_as_number == 73
|| (word_3_is_int && word_3_as_number == 73) || "RR73" == word_3
|| "RR73" == word_3)) { || ("R" == word_3 && m_QSOProgress != REPORT))) {
if(m_mode=="FT4" and "RR73" == word_3) m_dateTimeRcvdRR73=QDateTime::currentDateTimeUtc(); if(m_mode=="FT4" and "RR73" == word_3) m_dateTimeRcvdRR73=QDateTime::currentDateTimeUtc();
m_bTUmsg=false; m_bTUmsg=false;
m_nextCall=""; //### Temporary: disable use of "TU;" message m_nextCall=""; //### Temporary: disable use of "TU;" message
@ -5013,16 +5012,30 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
ui->tx3->setText(t); ui->tx3->setText(t);
m_bTUmsg=true; m_bTUmsg=true;
} else { } else {
if(SpecOp::RTTY == m_config.special_op_id()) { if (m_QSOProgress > CALLING && m_QSOProgress < SIGNOFF
logQSOTimer.start(0); && SpecOp::NONE < m_config.special_op_id () && SpecOp::FOX > m_config.special_op_id ()
m_ntx=6; && ("RR73" == word_3 || 73 == word_3_as_number))
ui->txrb6->setChecked(true); {
} else { logQSOTimer.start(0);
m_ntx=5; m_ntx=6;
ui->txrb5->setChecked(true); ui->txrb6->setChecked(true);
} }
else if (word_3.contains (QRegularExpression {"^R(?!R73|RR)"})
&& m_QSOProgress != ROGER_REPORT)
{
m_ntx=4;
ui->txrb4->setChecked(true);
}
else
{
m_ntx=5;
ui->txrb5->setChecked(true);
}
} }
m_QSOProgress = SIGNOFF; if (m_QSOProgress >= ROGER_REPORT)
{
m_QSOProgress = SIGNOFF;
}
} else if((m_QSOProgress >= REPORT } else if((m_QSOProgress >= REPORT
|| (m_QSOProgress >= REPLYING && || (m_QSOProgress >= REPLYING &&
(m_mode=="MSK144" or m_mode=="FT8" or m_mode=="FT4"))) (m_mode=="MSK144" or m_mode=="FT8" or m_mode=="FT4")))
@ -5037,30 +5050,35 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
ui->txrb4->setChecked(true); ui->txrb4->setChecked(true);
} else if (m_QSOProgress >= CALLING) } else if (m_QSOProgress >= CALLING)
{ {
if (word_3_is_int if ((word_3_as_number >= -50 && word_3_as_number <= 49)
&& ((word_3_as_number >= -50 && word_3_as_number <= 49) || (word_3_as_number >= 529 && word_3_as_number <= 599))
|| (word_3_as_number >= 529 && word_3_as_number <= 599))) { {
if(SpecOp::EU_VHF==m_config.special_op_id() or if(SpecOp::EU_VHF==m_config.special_op_id() or
SpecOp::FIELD_DAY==m_config.special_op_id() or SpecOp::FIELD_DAY==m_config.special_op_id() or
SpecOp::RTTY==m_config.special_op_id()) { SpecOp::RTTY==m_config.special_op_id())
setTxMsg(2); {
m_QSOProgress=REPORT; setTxMsg(2);
m_QSOProgress=REPORT;
}
else
{
if (word_3.startsWith ("R-") || word_3.startsWith ("R+"))
{
setTxMsg(4);
m_QSOProgress=ROGERS;
}
else
{
setTxMsg (3);
m_QSOProgress = ROGER_REPORT;
}
}
} }
else {
setTxMsg (3);
m_QSOProgress = ROGER_REPORT;
}
} else {
if (word_3.startsWith ("R-") || word_3.startsWith ("R+")) {
setTxMsg(4);
m_QSOProgress=ROGERS;
}
} }
} else
else { // nothing for us
{ // nothing for us return;
return; }
}
} }
} }
else if (m_QSOProgress >= ROGERS else if (m_QSOProgress >= ROGERS
@ -5138,7 +5156,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
} }
QString s1 = m_QSOText.trimmed (); QString s1 = m_QSOText.trimmed ();
QString s2 = message.string ().trimmed(); QString s2 = message.clean_string ().trimmed();
if (s1!=s2 and !message.isTX()) { if (s1!=s2 and !message.isTX()) {
if (!s2.contains(m_baseCall) or m_mode=="MSK144") { // Taken care of elsewhere if for_us and slow mode if (!s2.contains(m_baseCall) or m_mode=="MSK144") { // Taken care of elsewhere if for_us and slow mode
ui->decodedTextBrowser2->displayDecodedText(message, m_baseCall,m_mode,m_config.DXCC(), ui->decodedTextBrowser2->displayDecodedText(message, m_baseCall,m_mode,m_config.DXCC(),
@ -5711,7 +5729,7 @@ void MainWindow::msgtype(QString t, QLineEdit* tx) //msgtype()
p.setColor(QPalette::Base,"#66ffff"); //light blue p.setColor(QPalette::Base,"#66ffff"); //light blue
} else { } else {
p.setColor(QPalette::Base,Qt::transparent); p.setColor(QPalette::Base,Qt::transparent);
if(m_mode=="MSK144" and t.mid(0,1)=="<") { if ("MSK144" == m_mode && t.count ('<') == 1) {
p.setColor(QPalette::Base,"#00ffff"); //another light blue p.setColor(QPalette::Base,"#00ffff"); //another light blue
} }
} }
@ -6488,6 +6506,7 @@ void MainWindow::on_actionMSK144_triggered()
} else { } else {
ui->labDXped->setVisible(true); ui->labDXped->setVisible(true);
ui->labDXped->setText(t0); ui->labDXped->setText(t0);
on_contest_log_action_triggered();
} }
} }