Merge branch 'hotfix-2.2.2'

This commit is contained in:
Bill Somerville 2020-06-21 23:57:58 +01:00
commit 0d9b9694f4
No known key found for this signature in database
GPG Key ID: D864B06D1E81618F
56 changed files with 3795 additions and 2923 deletions

View File

@ -67,16 +67,34 @@ public:
private:
Q_SLOT void start_recording ()
{
qtout << "started recording at " << QDateTime::currentDateTimeUtc ().toString ("hh:mm:ss.zzz UTC") << endl;
qtout << "started recording at " << QDateTime::currentDateTimeUtc ().toString ("hh:mm:ss.zzz UTC")
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
source_.start (output_);
if (!notify_interval_) QTimer::singleShot (duration_ * 1000, Qt::PreciseTimer, this, &Record::stop_recording);
qtout << QString {"buffer size used is: %1"}.arg (source_.bufferSize ()) << endl;
qtout << QString {"buffer size used is: %1"}.arg (source_.bufferSize ())
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
}
Q_SLOT void notify ()
{
auto length = source_.elapsedUSecs ();
qtout << QString {"%1 μs recorded\r"}.arg (length) << flush;
qtout << QString {"%1 μs recorded\r"}.arg (length)
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
<< Qt::flush
#else
<< flush
#endif
;
if (length >= duration_ * 1000 * 1000) stop_recording ();
}
@ -85,7 +103,13 @@ private:
auto length = source_.elapsedUSecs ();
source_.stop ();
qtout << QString {"%1 μs recorded "}.arg (length) << '(' << source_.format ().framesForBytes (output_->size ()) << " frames recorded)\n";
qtout << "stopped recording at " << QDateTime::currentDateTimeUtc ().toString ("hh:mm:ss.zzz UTC") << endl;
qtout << "stopped recording at " << QDateTime::currentDateTimeUtc ().toString ("hh:mm:ss.zzz UTC")
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
Q_EMIT done ();
}
@ -134,15 +158,33 @@ public:
private:
Q_SLOT void start_playback ()
{
qtout << "started playback at " << QDateTime::currentDateTimeUtc ().toString ("hh:mm:ss.zzz UTC") << endl;
qtout << "started playback at " << QDateTime::currentDateTimeUtc ().toString ("hh:mm:ss.zzz UTC")
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
sink_.start (input_);
qtout << QString {"buffer size used is: %1 (%2 frames)"}.arg (sink_.bufferSize ()).arg (sink_.format ().framesForBytes (sink_.bufferSize ())) << endl;
qtout << QString {"buffer size used is: %1 (%2 frames)"}.arg (sink_.bufferSize ()).arg (sink_.format ().framesForBytes (sink_.bufferSize ()))
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
}
Q_SLOT void notify ()
{
auto length = sink_.elapsedUSecs ();
qtout << QString {"%1 μs rendered\r"}.arg (length) << flush;
qtout << QString {"%1 μs rendered\r"}.arg (length) <<
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
Qt::flush
#else
flush
#endif
;
}
Q_SLOT void sink_state_changed (QAudio::State state)
@ -175,7 +217,13 @@ private:
auto length = sink_.elapsedUSecs ();
sink_.stop ();
qtout << QString {"%1 μs rendered "}.arg (length) << '(' << sink_.format ().framesForBytes (input_->size ()) << " frames rendered)\n";
qtout << "stopped playback at " << QDateTime::currentDateTimeUtc ().toString ("hh:mm:ss.zzz UTC") << endl;
qtout << "stopped playback at " << QDateTime::currentDateTimeUtc ().toString ("hh:mm:ss.zzz UTC")
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
Q_EMIT done ();
}
@ -258,7 +306,13 @@ int main(int argc, char *argv[])
int n {0};
for (auto const& device : input_devices)
{
qtout << ++n << " - [" << device.deviceName () << ']' << endl;
qtout << ++n << " - [" << device.deviceName () << ']'
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
}
return 0;
}
@ -269,7 +323,13 @@ int main(int argc, char *argv[])
int n {0};
for (auto const& device : output_devices)
{
qtout << ++n << " - [" << device.deviceName () << ']' << endl;
qtout << ++n << " - [" << device.deviceName () << ']'
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
}
return 0;
}
@ -352,7 +412,13 @@ int main(int argc, char *argv[])
auto source = input_device ? input_devices[input_device - 1] : QAudioDeviceInfo::defaultInputDevice ();
if (!source.isFormatSupported (audio_format))
{
qtout << "warning, requested format not supported, using nearest" << endl;
qtout << "warning, requested format not supported, using nearest"
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
audio_format = source.nearestFormat (audio_format);
}
BWFFile output_file {audio_format, ofi.filePath ()};

View File

@ -15,7 +15,7 @@ if (EXISTS "${SOURCE_DIR}/.svn")
REGEX "^[^?].*$"
)
if (__svn_changes)
message (WARNING "Source tree based on revision ${MY_WC_LAST_CHANGED_REV} appears to have local changes")
message (STATUS "Source tree based on revision ${MY_WC_LAST_CHANGED_REV} appears to have local changes")
set (MY_WC_LAST_CHANGED_REV "${MY_WC_LAST_CHANGED_REV}-dirty")
foreach (__svn_change ${__svn_changes})
message (STATUS "${__svn_change}")
@ -41,7 +41,7 @@ elseif (EXISTS "${SOURCE_DIR}/.git")
REGEX "^diff-tree"
)
if ((NOT ${__git_svn_status} EQUAL 0) OR __svn_changes)
message (WARNING "Source tree based on revision ${MY_WC_LAST_CHANGED_REV} appears to have local changes")
message (STATUS "Source tree based on revision ${MY_WC_LAST_CHANGED_REV} appears to have local changes")
set (MY_WC_LAST_CHANGED_REV "${MY_WC_LAST_CHANGED_REV}-dirty")
endif ()
# write a file with the SVNVERSION define
@ -56,7 +56,7 @@ elseif (EXISTS "${SOURCE_DIR}/.git")
git_local_changes (${SOURCE_DIR} GIT_DIRTY)
string (SUBSTRING "${GIT_SHA1}" 0 6 GIT_SHA1)
if ("${GIT_DIRTY}" STREQUAL "DIRTY")
message (WARNING "Source tree based on revision ${GIT_REFSPEC} ${GIT_SHA1} appears to have local changes")
message (STATUS "Source tree based on revision ${GIT_REFSPEC} ${GIT_SHA1} appears to have local changes")
set (GIT_SHA1 "${GIT_SHA1}-dirty")
execute_process (COMMAND ${GIT_EXECUTABLE} --git-dir=${SOURCE_DIR}/.git --work-tree=${SOURCE_DIR} status
ERROR_QUIET

View File

@ -887,7 +887,7 @@ message (STATUS "hamlib_LIBRARY_DIRS: ${hamlib_LIBRARY_DIRS}")
#
# Widgets finds its own dependencies.
find_package (Qt5 COMPONENTS Widgets Multimedia PrintSupport Sql LinguistTools REQUIRED)
find_package (Qt5 COMPONENTS Widgets SerialPort Multimedia PrintSupport Sql LinguistTools REQUIRED)
if (WIN32)
add_definitions (-DQT_NEEDS_QTMAIN)
@ -1111,9 +1111,7 @@ set (LANGUAGES
)
foreach (lang_ ${LANGUAGES})
file (TO_NATIVE_PATH ${CMAKE_SOURCE_DIR}/translations/wsjtx_${lang_}.ts ts_)
if (EXISTS "${ts_}")
list (APPEND TS_FILES ${ts_})
endif ()
list (APPEND TS_FILES ${ts_})
set (qt_translations_ "${QT_TRANSLATIONS_DIR}/qtbase_${lang_}.qm")
if (EXISTS "${qt_translations_}")
add_custom_command (
@ -1378,9 +1376,9 @@ set_target_properties (wsjtx PROPERTIES
target_include_directories (wsjtx PRIVATE ${FFTW3_INCLUDE_DIRS})
if (APPLE)
target_link_libraries (wsjtx wsjt_fort wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
target_link_libraries (wsjtx Qt5::SerialPort wsjt_fort wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
else ()
target_link_libraries (wsjtx wsjt_fort_omp wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
target_link_libraries (wsjtx Qt5::SerialPort wsjt_fort_omp wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
if (OpenMP_C_FLAGS)
set_target_properties (wsjtx PROPERTIES
COMPILE_FLAGS "${OpenMP_C_FLAGS}"
@ -1396,7 +1394,6 @@ else ()
)
endif ()
endif ()
qt5_use_modules (wsjtx SerialPort) # not sure why the interface link library syntax above doesn't work
# make a library for WSJT-X UDP servers
# add_library (wsjtx_udp SHARED ${UDP_library_CXXSRCS})
@ -1416,8 +1413,7 @@ set_target_properties (wsjtx_udp-static PROPERTIES
OUTPUT_NAME wsjtx_udp
)
target_compile_definitions (wsjtx_udp-static PUBLIC UDP_STATIC_DEFINE)
#qt5_use_modules (wsjtx_udp Network)
qt5_use_modules (wsjtx_udp-static Network Gui)
target_link_libraries (wsjtx_udp-static Qt5::Network Qt5::Gui)
generate_export_header (wsjtx_udp-static BASE_NAME udp)
add_executable (udp_daemon UDPExamples/UDPDaemon.cpp UDPExamples/udp_daemon.rc ${WSJTX_ICON_FILE})

View File

@ -230,7 +230,7 @@ namespace
|IL|IN|KS|KY|LA|LAX|MAR|MB|MDC
|ME|MI|MN|MO|MS|MT|NC|ND|NE|NFL
|NH|NL|NLI|NM|NNJ|NNY|NT|NTX|NV
|OH|OK|ONE|ONN|ONS|OR|ORG|PAC
|OH|OK|ONE|ONN|ONS|OR|ORG|PAC|PE
|PR|QC|RI|SB|SC|SCV|SD|SDG|SF
|SFL|SJV|SK|SNJ|STX|SV|TN|UT|VA
|VI|VT|WCF|WI|WMA|WNY|WPA|WTX

View File

@ -1,47 +1,28 @@
Notes on WSJT-X Installation for Mac OS X
-----------------------------------------
Updated 21 October 2018
-----------------------
If you have already downloaded a previous version of WSJT-X then I suggest
you change the name in the Applications folder from WSJT-X to WSJT-X_previous
before proceeding.
If you have installed a previous version of WSJT-X before then there is no
need to change anything on your system so proceed to NEXT.
If you have installed a previous version of WSJT-X before, then there is no
need to change anything on your system so proceed to NEXT. If you upgrade macOS
it is possible that you might need to re-install the sysctl.conf file.
BEGIN:
There are some system matters you must deal with first. Open a Terminal window
by going to Applications->Utilities and clicking on Terminal.
Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's web-site.
Along with this ReadMe file there is a file: sysctl.conf. Drag this file to your Desktop.
Now open a Terminal window by going to Applications->Utilities and clicking on Terminal.
WSJT-X makes use of a block of memory which is shared between different parts of
the code. The normal allocation of shared memory on a Mac is insufficient and this
has to be increased. You should use a Mac editor to examine sysctl.conf.
Along with this ReadMe file there is a file: sysctl.conf which must be copied to a
system area by typing this line in the Terminal window and then pressing the Return key.
There are two important parameters that you need to consider. shmmax determines the
amount of shared memory that must be allocated for WSJT-X to operate. This is 14680064 (14MB)
and this is defined in the sysctl.conf file and should not be changed.
sudo cp /Volumes/WSJT-X/sysctl.conf /etc
It is possible to run more than one instance of WSJT-X simultaneously. See
"Section 14. Platform Dependencies" in the User Guide. The second important parameter
shmall=17920 determines how many instances are permitted. This is calculated as:
(shmall x 4096/14680064) = 5.
The sysctl.conf file is configured to permit up to 5 instances of wsjtx to run simultaneously.
If this limitation is acceptable then you can continue to install the sysctl.conf file without making any
alterations. Otherwise you must edit the file to increase shmall according to this calculation.
Now move this file into place for the system to use by typing: (Note this assumes that
you really did drag this file to your Desktop as required earlier.)
sudo cp "$HOME/Desktop/sysctl.conf" /etc/
sudo chmod 664 /etc/sysctl.conf
sudo chown root:wheel /etc/sysctl.conf
and then reboot your Mac. This is necessary to install the changes. After the
you will be asked for your normal password because authorisation is needed to copy this file.
(Your password will not be echoed but press the Return key when completed.)
Now re-boot your Mac. This is necessary to install the changes. After the
reboot you should re-open the Terminal window as before and you can check that the
change has been made by typing:
@ -50,11 +31,10 @@ change has been made by typing:
If shmmax is not shown as 14680064 then contact me since WSJT-X will fail to load with
an error message: "Unable to create shared memory segment".
You are now finished with system changes. You should make certain that NO error messages
have been produced during these steps. You can now close the Terminal window. It will
not be necessary to repeat this procedure again, even when you download an updated
version of WSJT-X.
You can now close the Terminal window. It will not be necessary to repeat this procedure
again, even when you download an updated version of WSJT-X. It might be necessary if you
upgrade macOS.
NEXT:
Drag the WSJT-X app to your preferred location, such as Applications.
@ -68,11 +48,8 @@ under the WSJT-X Menu and fill in various station details on the General panel.
I recommend checking the 4 boxes under the Display heading and the first 4 boxes under
the Behaviour heading.
IMPORTANT: If you are using macOS 10.14 (Mojave) it is important to note that the default setting
for audio input is "block". In order to receive audio from WSJT-X you must visit
System Preferences > Security & Privacy > Privacy and, with WSJT-X launched, select "Microphone"
under Location Services and wsjtx should appear in the panel. Check the "Allow" box. You will
have to quit WSJT-X for this change to take effect.
Depending on your macOS you might see a pop-up window suggesting that wsjtx wants to use the
microphone. What this means is that audio input must be allowed. Agree.
Next visit the Audio panel and select the Audio Codec you use to communicate between
WSJT-X and your rig. There are so many audio interfaces available that it is not
@ -80,31 +57,43 @@ possible to give detailed advice on selection. If you have difficulties contact
Note the location of the Save Directory. Decoded wave forms are located here.
Look at the Reporting panel. If you check the "Prompt me" box, a logging panel will appear
at the end of the QSO. Two log files are provided in Library/Application Support/WSJT-X.
These are a simple wsjtx.log file and wsjtx_log.adi which is formatted for use with
logging databases. The "File" menu bar items include a button "Open log directory"
to open the log directory in Finder for you, ready for processing by any logging
application you use.
at the end of the QSO. Visit Section 11 of the User Guide for information about log files
and how to access them.
Finally, visit the Radio panel. WSJT-X is most effective when operated with CAT
control. You will need to install the relevant Mac driver for your rig. This must
be located in the device driver directory /dev. You should install your driver
and then re-launch WSJT-X. Return to the the Radio panel in Preferences and in
the "Serial port" panel select your driver from the list that is presented. If
for some reason your driver is not shown, then insert the full name
of your driver in the Serial Port panel. Such as: /dev/cu.PL2303-00002226 or
whatever driver you have. The /dev/ prefix is mandatory. Set the relevant
communication parameters as required by your transceiver and click "Test CAT" to
check.
control. You will need to install the relevant Mac device driver for your rig,
and then re-launch WSJT-X. Return to the Radio panel in Preferences and in
the "Serial port" panel select your driver from the list that is presented. If you
do not know where to get an appropriate driver, contact me.
WSJT-X needs the Mac clock to be accurate. Visit System Preferences > Date & Time
and make sure that date and time are set automatically. The drop-down menu will
and make sure that Date and Time are set automatically. The drop-down menu will
normally offer you several time servers to choose from.
On the Help menu, have a look at the new Online User's Guide for operational hints
and tips.
and tips and possible solutions to any problem you might have.
Please email me if you have problems.
--- John G4KLA (g4kla@rmnjmn.co.uk)
Addendum: Information about sysctl.conf and multiple instances of wsjt-x.
WSJT-X makes use of a block of memory which is shared between different parts of
the code. The normal allocation of shared memory on a Mac is insufficient and this
has to be increased. The sysctl.conf file is used for this purpose. You can
use a Mac editor to examine sysctl.conf. (Do not use another editor - the file
would be probably be corrupted.)
There are two important parameters that you need to consider. shmmax determines the
amount of shared memory that must be allocated for WSJT-X to operate. This is 14680064 (14MB)
and this is defined in the sysctl.conf file and should not be changed.
It is possible to run more than one instance of WSJT-X simultaneously. See
"Section 16.2 Frequently asked Questions" in the User Guide. The second important parameter
shmall=17920 determines how many instances are permitted. This is calculated as:
(shmall x 4096/14680064) = 5.
The sysctl.conf file is configured to permit up to 5 instances of wsjtx to run simultaneously.
If this limitation is acceptable then you can continue to install the sysctl.conf file without making any
alterations. Otherwise you must edit the file to increase shmall according to this calculation.

View File

@ -3,6 +3,7 @@
#include <QStringList>
#include <QRegularExpression>
#include <QDebug>
#include "qt_helpers.hpp"
extern "C" {
bool stdmsg_(char const * msg, fortran_charlen_t);
@ -58,7 +59,7 @@ QStringList DecodedText::messageWords () const
return words_re.match(t).capturedTexts();
}
// simple word split for free text messages
auto words = message_.split (' ', QString::SkipEmptyParts);
auto words = message_.split (' ', SkipEmptyParts);
// add whole message as item 0 to mimic RE capture list
words.prepend (message_);
return words;
@ -122,7 +123,7 @@ bool DecodedText::report(QString const& myBaseCall, QString const& dxBaseCall, /
{
if (message_.size () < 1) return false;
QStringList const& w = message_.split(" ",QString::SkipEmptyParts);
QStringList const& w = message_.split(" ", SkipEmptyParts);
if (w.size ()
&& is_standard_ && (w[0] == myBaseCall
|| w[0].endsWith ("/" + myBaseCall)

View File

@ -49,10 +49,12 @@ public:
void display (QUrl const& url, QString const& name_we)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
if (QNetworkAccessManager::Accessible != qnam_->networkAccessible ()) {
// try and recover network access for QNAM
qnam_->setNetworkAccessible (QNetworkAccessManager::Accessible);
}
#endif
// try and find a localized manual
auto lang = QLocale::system ().name ();

View File

@ -2,6 +2,9 @@
#include <limits>
#include <qmath.h>
#include <QDateTime>
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
#include <QRandomGenerator>
#endif
#include <QDebug>
#include "widgets/mainwindow.h" // TODO: G4WJS - break this dependency
#include "Audio/soundout.h"
@ -278,8 +281,13 @@ qint64 Modulator::readData (char * data, qint64 maxSize)
int j=m_ic/480;
if(m_fSpread>0.0 and j!=m_j0) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
float x1=QRandomGenerator::global ()->generateDouble ();
float x2=QRandomGenerator::global ()->generateDouble ();
#else
float x1=(float)qrand()/RAND_MAX;
float x2=(float)qrand()/RAND_MAX;
#endif
toneFrequency = m_toneFrequency0 + 0.5*m_fSpread*(x1+x2-1.0);
m_dphi = m_twoPi * toneFrequency / m_frameRate;
m_j0=j;

26
NEWS
View File

@ -13,6 +13,32 @@
Copyright 2001 - 2020 by Joe Taylor, K1JT.
Release: WSJT-X 2.2.2
June 22, 2020
---------------------
WSJT-X v2.2.2 is a bug fix release, mainly to incorporate the new RAC
section PE into the FT8/FT4/MSK144 Contest Mode for Field Day.
- Stations intending to operate in Field Day (FD) are urged to
upgrade to this release, without it you cannot set your section to
PE, and of equal importance you cannot decode contest messages from
stations who are operating from PE without this upgrade.
- FT8 decoder speeded up in Normal and Fast modes. This change gives
a speed of decoding closer to that of v2.1.2 without compromising
the number of decodes. It is particularly targeted for slower
single board computer users such as the Raspberry Pi Model 3 or
similar.
- Thanks to our user interface language translation contributors for
many improvements to the translated strings.
- The DX Grid field is now cleared automatically when the DX Call
field is changed. Care should be taken to complete entry of a
callsign before entering a grid square.
Release: WSJT-X 2.2.1
June 6, 2020
---------------------

View File

@ -69,11 +69,13 @@ public:
void download (QUrl url)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
if (QNetworkAccessManager::Accessible != network_manager_->networkAccessible ())
{
// try and recover network access for QNAM
network_manager_->setNetworkAccessible (QNetworkAccessManager::Accessible);
}
#endif
QNetworkRequest request {url};
request.setRawHeader ("User-Agent", "WSJT LotW User Downloader");

View File

@ -423,6 +423,7 @@ MessageClient::MessageClient (QString const& id, QString const& version, QString
: QObject {self}
, m_ {id, version, revision, server_port, this}
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
connect (&*m_, static_cast<void (impl::*) (impl::SocketError)> (&impl::error)
, [this] (impl::SocketError e)
{
@ -441,6 +442,11 @@ MessageClient::MessageClient (QString const& id, QString const& version, QString
Q_EMIT error (m_->errorString ());
}
});
#else
connect (&*m_, &impl::errorOccurred, [this] (impl::SocketError) {
Q_EMIT error (m_->errorString ());
});
#endif
set_server (server);
}

View File

@ -7,6 +7,9 @@
#include <QHostInfo>
#include <QTimer>
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
#include <QRandomGenerator>
#endif
#include "Network/MessageClient.hpp"
@ -43,7 +46,11 @@ PSK_Reporter::PSK_Reporter(MessageClient * message_client, QObject *parent) :
"00960004"; // Report time
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
m_randomId_h = QString("%1").arg(qrand(),8,16,QChar('0'));
#else
m_randomId_h = QString("%1").arg(QRandomGenerator::global ()->generate (), 8, 16, QChar('0'));
#endif
QHostInfo::lookupHost("report.pskreporter.info", this, SLOT(dnsLookupResult(QHostInfo)));

View File

@ -208,10 +208,12 @@ QString WSPRNet::urlEncodeSpot(QHash<QString,QString> const& query)
void WSPRNet::work()
{
if (!urlQueue.isEmpty()) {
#if QT_VERSION < QT_VERSION_CHECK (5, 15, 0)
if (QNetworkAccessManager::Accessible != networkManager->networkAccessible ()) {
// try and recover network access for QNAM
networkManager->setNetworkAccessible (QNetworkAccessManager::Accessible);
}
#endif
QUrl url(urlQueue.dequeue());
QNetworkRequest request(url);
m_outstandingRequests << networkManager->get(request);

View File

@ -13,6 +13,32 @@
Copyright 2001 - 2020 by Joe Taylor, K1JT.
Release: WSJT-X 2.2.2
June 22, 2020
---------------------
WSJT-X v2.2.2 is a bug fix release, mainly to incorporate the new RAC
section PE into the FT8/FT4/MSK144 Contest Mode for Field Day.
- Stations intending to operate in Field Day (FD) are urged to
upgrade to this release, without it you cannot set your section to
PE, and of equal importance you cannot decode contest messages from
stations who are operating from PE without this upgrade.
- FT8 decoder speeded up in Normal and Fast modes. This change gives
a speed of decoding closer to that of v2.1.2 without compromising
the number of decodes. It is particularly targeted for slower
single board computer users such as the Raspberry Pi Model 3 or
similar.
- Thanks to our user interface language translation contributors for
many improvements to the translated strings.
- The DX Grid field is now cleared automatically when the DX Call
field is changed. Care should be taken to complete entry of a
callsign before entering a grid square.
Release: WSJT-X 2.2.1
June 6, 2020
---------------------

View File

@ -101,17 +101,17 @@ SampleDownloader::impl::impl (QSettings * settings
setWindowTitle (QApplication::applicationName () + " - " + tr ("Download Samples"));
button_box_.button (QDialogButtonBox::Close)->setDefault (true);
button_box_.addButton ("&Abort", QDialogButtonBox::DestructiveRole);
button_box_.addButton ("&Refresh", QDialogButtonBox::ResetRole);
button_box_.addButton (tr ("&Abort"), QDialogButtonBox::DestructiveRole);
button_box_.addButton (tr ("&Refresh"), QDialogButtonBox::ResetRole);
left_layout_.addWidget (&directory_);
auto details_button = button_box_.addButton ("&Details", QDialogButtonBox::HelpRole);
auto details_button = button_box_.addButton (tr ("&Details"), QDialogButtonBox::HelpRole);
details_button->setCheckable (true);
details_widget_.hide ();
details_layout_.setMargin (0);
details_layout_.addRow ("Base URL for samples:", &url_line_edit_);
details_layout_.addRow ("Only use HTTP:", &http_only_check_box_);
http_only_check_box_.setToolTip ("Check this is you get SSL/TLS errors");
details_layout_.addRow (tr ("Base URL for samples:"), &url_line_edit_);
details_layout_.addRow (tr ("Only use HTTP:"), &http_only_check_box_);
http_only_check_box_.setToolTip (tr ("Check this is you get SSL/TLS errors"));
details_widget_.setLayout (&details_layout_);
main_layout_.addLayout (&left_layout_, 0, 0);

View File

@ -48,7 +48,7 @@ Directory::Directory (Configuration const * configuration
file_icon_.addPixmap (style ()->standardPixmap (QStyle::SP_FileIcon));
setColumnCount (2);
setHeaderLabels ({"File", "Progress"});
setHeaderLabels ({tr ("File"), tr ("Progress")});
header ()->setSectionResizeMode (QHeaderView::ResizeToContents);
setItemDelegate (&item_delegate_);

View File

@ -121,10 +121,12 @@ bool RemoteFile::sync (QUrl const& url, bool local, bool force)
void RemoteFile::download (QUrl url)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
if (QNetworkAccessManager::Accessible != network_manager_->networkAccessible ()) {
// try and recover network access for QNAM
network_manager_->setNetworkAccessible (QNetworkAccessManager::Accessible);
}
#endif
if (url.isValid () && (!QSslSocket::supportsSsl () || http_only_))
{

View File

@ -78,7 +78,12 @@ void TraceFile::impl::message_handler (QtMsgType type, QMessageLogContext const&
Q_ASSERT_X (current_stream_, "TraceFile:message_handler", "no stream to write to");
{
QMutexLocker lock {&mutex_}; // thread safety - serialize writes to the trace file
*current_stream_ << qFormatLogMessage (type, context, msg) << endl;
*current_stream_ << qFormatLogMessage (type, context, msg) <<
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
endl;
#else
Qt::endl;
#endif
}
if (QtFatalMsg == type)

View File

@ -10,6 +10,7 @@
#include <QDir>
#include "Network/NetworkServerLookup.hpp"
#include "qt_helpers.hpp"
namespace
{
@ -167,7 +168,7 @@ int HRDTransceiver::do_start ()
HRD_info << "Id: " << id << "\n";
HRD_info << "Version: " << version << "\n";
auto radios = send_command ("get radios", false, false).trimmed ().split (',', QString::SkipEmptyParts);
auto radios = send_command ("get radios", false, false).trimmed ().split (',', SkipEmptyParts);
if (radios.isEmpty ())
{
TRACE_CAT ("HRDTransceiver", "no rig found");
@ -178,7 +179,7 @@ int HRDTransceiver::do_start ()
Q_FOREACH (auto const& radio, radios)
{
HRD_info << "\t" << radio << "\n";
auto entries = radio.trimmed ().split (':', QString::SkipEmptyParts);
auto entries = radio.trimmed ().split (':', SkipEmptyParts);
radios_.push_back (std::forward_as_tuple (entries[0].toUInt (), entries[1]));
}
@ -202,11 +203,11 @@ int HRDTransceiver::do_start ()
HRD_info << "VFO count: " << vfo_count_ << "\n";
TRACE_CAT ("HRDTransceiver", "vfo count:" << vfo_count_);
buttons_ = send_command ("get buttons").trimmed ().split (',', QString::SkipEmptyParts).replaceInStrings (" ", "~");
buttons_ = send_command ("get buttons").trimmed ().split (',', SkipEmptyParts).replaceInStrings (" ", "~");
TRACE_CAT ("HRDTransceiver", "HRD Buttons: " << buttons_);
HRD_info << "Buttons: {" << buttons_.join (", ") << "}\n";
dropdown_names_ = send_command ("get dropdowns").trimmed ().split (',', QString::SkipEmptyParts);
dropdown_names_ = send_command ("get dropdowns").trimmed ().split (',', SkipEmptyParts);
TRACE_CAT ("HRDTransceiver", "Dropdowns:");
HRD_info << "Dropdowns:\n";
Q_FOREACH (auto const& dd, dropdown_names_)
@ -217,12 +218,12 @@ int HRDTransceiver::do_start ()
dropdowns_[dd] = selections;
}
slider_names_ = send_command ("get sliders").trimmed ().split (',', QString::SkipEmptyParts).replaceInStrings (" ", "~");
slider_names_ = send_command ("get sliders").trimmed ().split (',', SkipEmptyParts).replaceInStrings (" ", "~");
TRACE_CAT ("HRDTransceiver", "Sliders:-");
HRD_info << "Sliders:\n";
Q_FOREACH (auto const& s, slider_names_)
{
auto range = send_command ("get slider-range " + current_radio_name + " " + s).trimmed ().split (',', QString::SkipEmptyParts);
auto range = send_command ("get slider-range " + current_radio_name + " " + s).trimmed ().split (',', SkipEmptyParts);
TRACE_CAT ("HRDTransceiver", "\t" << s << ": {" << range.join (", ") << "}");
HRD_info << "\t" << s << ": {" << range.join (", ") << "}\n";
sliders_[s] = range;
@ -601,7 +602,7 @@ void HRDTransceiver::do_frequency (Frequency f, MODE m, bool /*no_ignore*/)
auto fo_string = QString::number (f);
if (vfo_count_ > 1 && reversed_)
{
auto frequencies = send_command ("get frequencies").trimmed ().split ('-', QString::SkipEmptyParts);
auto frequencies = send_command ("get frequencies").trimmed ().split ('-', SkipEmptyParts);
send_simple_command ("set frequencies-hz " + QString::number (frequencies[0].toUInt ()) + ' ' + fo_string);
}
else
@ -687,14 +688,14 @@ void HRDTransceiver::do_tx_frequency (Frequency tx, MODE mode, bool /*no_ignore*
{
Q_ASSERT (vfo_count_ > 1);
auto frequencies = send_command ("get frequencies").trimmed ().split ('-', QString::SkipEmptyParts);
auto frequencies = send_command ("get frequencies").trimmed ().split ('-', SkipEmptyParts);
send_simple_command ("set frequencies-hz " + fo_string + ' ' + QString::number (frequencies[1].toUInt ()));
}
else
{
if (vfo_count_ > 1)
{
auto frequencies = send_command ("get frequencies").trimmed ().split ('-', QString::SkipEmptyParts);
auto frequencies = send_command ("get frequencies").trimmed ().split ('-', SkipEmptyParts);
send_simple_command ("set frequencies-hz " + QString::number (frequencies[0].toUInt ()) + ' ' + fo_string);
}
else if ((vfo_B_button_ >= 0 && vfo_A_button_ >= 0) || vfo_toggle_button_ >= 0)
@ -986,7 +987,7 @@ void HRDTransceiver::do_poll ()
if (vfo_count_ > 1)
{
auto frequencies = send_command ("get frequencies", quiet).trimmed ().split ('-', QString::SkipEmptyParts);
auto frequencies = send_command ("get frequencies", quiet).trimmed ().split ('-', SkipEmptyParts);
update_rx_frequency (frequencies[reversed_ ? 1 : 0].toUInt ());
update_other_frequency (frequencies[reversed_ ? 0 : 1].toUInt ());
}

View File

@ -65,6 +65,16 @@ namespace
{
TransceiverFactory::Transceivers * rigs = reinterpret_cast<TransceiverFactory::Transceivers *> (callback_data);
// We can't use this one because it is only for testing Hamlib and
// would confuse users, possibly causing operating on the wrong
// frequency!
#ifdef RIG_MODEL_DUMMY_NOVFO
if (RIG_MODEL_DUMMY_NOVFO == caps->rig_model)
{
return 1;
}
#endif
QString key;
if (RIG_MODEL_DUMMY == caps->rig_model)
{
@ -185,6 +195,7 @@ HamlibTransceiver::HamlibTransceiver (TransceiverFactory::PTTMethod ptt_type, QS
QObject * parent)
: PollingTransceiver {0, parent}
, rig_ {rig_init (RIG_MODEL_DUMMY)}
, ptt_only_ {true}
, back_ptt_port_ {false}
, one_VFO_ {false}
, is_dummy_ {true}
@ -238,6 +249,7 @@ HamlibTransceiver::HamlibTransceiver (int model_number, TransceiverFactory::Para
QObject * parent)
: PollingTransceiver {params.poll_interval, parent}
, rig_ {rig_init (model_number)}
, ptt_only_ {false}
, back_ptt_port_ {TransceiverFactory::TX_audio_source_rear == params.audio_source}
, one_VFO_ {false}
, is_dummy_ {RIG_MODEL_DUMMY == model_number}
@ -581,7 +593,7 @@ int HamlibTransceiver::do_start ()
tickle_hamlib_ = true;
if (is_dummy_ && dummy_frequency_)
if (is_dummy_ && !ptt_only_ && dummy_frequency_)
{
// return to where last dummy instance was
// TODO: this is going to break down if multiple dummy rigs are used
@ -642,7 +654,7 @@ int HamlibTransceiver::do_start ()
void HamlibTransceiver::do_stop ()
{
if (is_dummy_)
if (is_dummy_ && !ptt_only_)
{
rig_get_freq (rig_.data (), RIG_VFO_CURR, &dummy_frequency_);
dummy_frequency_ = std::round (dummy_frequency_);

View File

@ -45,6 +45,7 @@ public:
struct RIGDeleter {static void cleanup (RIG *);};
QScopedPointer<RIG, RIGDeleter> rig_;
bool ptt_only_; // we can use a dummy device for PTT
bool back_ptt_port_;
bool one_VFO_;
bool is_dummy_;

View File

@ -172,14 +172,14 @@ void TransceiverBase::shutdown ()
do_tx_frequency (0, UNK, true);
do_post_tx_frequency (0, UNK);
}
do_stop ();
do_post_stop ();
}
catch (...)
{
// don't care about exceptions
}
}
do_stop ();
do_post_stop ();
actual_ = TransceiverState {};
requested_ = TransceiverState {};
}

View File

@ -39,11 +39,18 @@ public:
Radio::register_types ();
connect (this, &QIODevice::readyRead, this, &MessageServer::impl::pending_datagrams);
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
connect (this, static_cast<void (impl::*) (SocketError)> (&impl::error)
, [this] (SocketError /* e */)
{
Q_EMIT self_->error (errorString ());
});
#else
connect (this, &impl::errorOccurred, [this] (SocketError /* e */)
{
Q_EMIT self_->error (errorString ());
});
#endif
connect (clock_, &QTimer::timeout, this, &impl::tick);
clock_->start (NetworkMessage::pulse * 1000);
}

View File

@ -1,6 +1,6 @@
# Version number components
set (WSJTX_VERSION_MAJOR 2)
set (WSJTX_VERSION_MINOR 2)
set (WSJTX_VERSION_PATCH 1)
set (WSJTX_VERSION_PATCH 2)
#set (WSJTX_RC 1) # release candidate number, comment out or zero for development versions
set (WSJTX_VERSION_IS_RELEASE 1) # set to 1 for final release build

View File

@ -242,7 +242,13 @@ namespace
QTextStream stream {&file};
Q_FOREACH (auto colour, colours_)
{
stream << colour.red () << ';' << colour.green () << ';' << colour.blue () << endl;
stream << colour.red () << ';' << colour.green () << ';' << colour.blue () <<
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
endl
#else
Qt::endl
#endif
;
}
}
else

View File

@ -1,3 +1,5 @@
//status=edited
A text box entitled Astronomical Data provides information needed for
tracking the sun or moon, compensating for EME Doppler shift, and
estimating EME Doppler spread and path degradation. Toggle the
@ -5,7 +7,7 @@ estimating EME Doppler spread and path degradation. Toggle the
image::AstroData_2.png[align="center",alt="Astronomical Data"]
Available information includes the current UTC *Date* and time; *Az*
Available information includes the current UTC *Date* and *Time*; *Az*
and *El*, azimuth and elevation of the moon at your own location, in
degrees; *SelfDop*, *Width*, and *Delay*, the Doppler shift, full
limb-to-limb Doppler spread in Hz, and delay of your own EME echoes in
@ -23,17 +25,17 @@ relative to the best possible time with the moon at perigee in a cold
part of the sky.
On the higher microwave bands, where Faraday rotation is minimal and
linear polarization is often used, spatial offset will reduce signal
levels. Some stations have implemented mechanical polarisation
adjustment to overcome this loss, and the amount of rotation needed is
linear polarization is often used, spatial offset reduces signal
levels. Some stations have implemented mechanical polarisation
adjustment to overcome this loss. The amount of rotation needed is
predicted in real time by the value of *Dpol*. Positive Dpol means
that the antenna should be rotated in a clockwise direction looking
from behind the antenna towards the moon. For a dish antenna, the
feed should similarly be rotated clockwise looking into the mouth of
the feed. A negative value for Dpol means anticlockwise rotation.
the feed. A negative value for Dpol means a counterclockwise rotation.
The state of the art for establishing three-dimensional locations of
The state-of-the-art for establishing three-dimensional locations of
the sun, moon, and planets at a specified time is embodied in a
numerical model of the solar system maintained at the Jet Propulsion
Laboratory. The model has been numerically integrated to produce

View File

@ -1,4 +1,4 @@
// Status=review
// Status=edited
At the center of the main window are a number of controls used when
making QSOs. Controls not relevant to a particular mode or submode
@ -7,41 +7,34 @@ may be "grayed out" (disabled) or removed from the display.
//.Misc Controls Center
image::misc-controls-center.png[align="center",alt="Misc Controls Center"]
* Check *Tx even* to transmit in even-numbered UTC minutes or
* Check *Tx even/1st* to transmit in even-numbered UTC minutes or
sequences, starting at 0. Uncheck this box to transmit in the odd
sequences. The correct selection is made automatically when you
double-click on a decoded text line, as described in the
<<TUTORIAL,Basic Operating Tutorial>>.
* The Tx and Rx audio frequencies can be set automatically by
double-clicking on decoded text or a signal in the waterfall. They
double-clicking decoded text or a signal in the waterfall. They
can also be adjusted using the spinner controls.
* You can copy values between the *Tx Freq* and *Rx Freq* boxes by
clicking on the up/down arrows between the controls. Your
on-the-air frequency is the sum of dial frequency and audio Tx
frequency. By convention we define the frequency of WSJT-X modes as
the frequency of the lowest tone.
* You can force Tx frequency to the current Rx frequency by clicking
the *Tx<-Rx* button, and vice-versa for *Rx<-Tx*. The on-the-air
frequency of your lowest JT9 or JT65 tone is the sum of dial frequency
and audio Tx frequency.
* Check the box *Hold Tx Freq* to ensure that the specified Tx
frequency is not changed automatically when you double-click on
decoded text or a signal in the waterfall.
* For modes lacking a multi-decode feature, or when *Enable
VHF/UHF/Microwave features* has been checked on the *Settings ->
General* tab, the *F Tol* control sets a frequency tolerance range
over which decoding will be attempted, centered on the Rx frequency.
* For modes lacking a multi-decode feature, or when *Enable VHF/UHF/Microwave features* has been checked on the *File -> Settings -> General* tab, the *F Tol* control sets a frequency tolerance range over which decoding is attempted, centered on the Rx frequency.
* The *Report* control lets you change a signal report that has been
inserted automatically. Typical reports for the various modes fall in
* The *Report* control lets you change an automatically inserted signal report. Typical reports for the various modes fall in
the range 30 to +20 dB. Remember that JT65 reports saturate at an
upper limit of -1 dB.
+
TIP: Consider reducing power if your QSO partner reports your
signal above -5 dB in one of the _WSJT-X_ slow modes. These are
supposed to be weak signal modes!
TIP: Consider reducing power if your QSO partner reports your signal above -5 dB in one of the _WSJT-X_ slow modes. These are supposed to be weak signal modes!
* In some circumstances, especially on VHF and higher bands, you can
select a supported submode of the active mode by using the *Submode*
@ -51,11 +44,11 @@ time and frequency synchronization with a received signal.
* Spinner control *T/R xx s* sets sequence lengths for transmission
and reception in ISCAT, MSK144, and the fast JT9 modes.
* With *Split operation* activated on the *Settings -> Radio* tab, in
* With *Split operation* activated on the *File -> Settings -> Radio* tab, in
MSK144 and the fast JT9 submodes you can activate the spinner control
*Tx CQ nnn* by checking the box to its right. The program will then
generate something like `CQ nnn K1ABC FN42` for your CQ message, where
`nnn` is the kHz portion of your current dial frequency,
`nnn` is the kHz portion of your current operating frequency,
in the range 010 to 999. Your CQ
message *Tx6* will then be transmitted at the calling frequency
selected in the *Tx CQ nnn* spinner control. All other messages will

View File

@ -1,16 +1,15 @@
// Status=review
// Status=edited
Controls related to frequency selection, received audio level, the
station being called, and date and time are found at lower left of the
station being called, and date and time are found in the lower, left-hand section of the
main window:
//.Misc Controls Left
image::misc-main-ui.png[align="center",alt="Misc Menu Items"]
* A drop-down list of frequencies and bands at upper left lets you
select the operating band and sets dial frequency to a value taken
from the *Frequencies* tab on the *Settings* window. If CAT control
is active the radio's dial frequency will be set accordingly; if not,
* A drop-down list of frequencies and bands in the upper, left-hand corner lets you
select the operating band. It also sets dial frequency to a value taken from the *Frequencies* tab on the *Settings* window. If CAT control
is active, the radio's dial frequency is set accordingly; if not,
you must tune the radio manually.
* Alternatively, you can enter a frequency (in MHz) or band name in

View File

@ -1,19 +1,17 @@
The following controls appear just under the decoded
text windows on the main screen. Some controls appear only in certain
operating modes.
// Status=edited
The following controls appear just under the decoded text windows on
the main screen:
//.Main UI
image::main-ui-controls.png[align="center",width=650,alt="Main UI Controls"]
* When *CQ only* is checked, only messages from stations calling CQ will
be displayed in the left text panel.
* When *CQ only* is checked, only messages from stations calling CQ are displayed in the left text panel.
* *Log QSO* raises a dialog window pre-filled with known information
about a QSO you have nearly completed. You can edit or add to this
information before clicking *OK* to log the QSO. If you check *Prompt
me to log QSO* on the *Settings -> Reporting* tab, the program will
raise the confirmation screen automatically when you send a message
containing +73+. *Start Date* and *Start Time* are set when you click
me to log QSO* on the *File -> Settings -> Reporting* tab, the program raises the confirmation screen automatically when you send a message containing +73+. *Start Date* and *Start Time* are set when you click
to send the *Tx 2* or *Tx 3* message, and backed up by one or two
sequence lengths, respectively. (Note that the actual start time may
have been earlier if repeats of early transmissions were required.)
@ -22,15 +20,15 @@ End date and time are set when the *Log QSO* screen is invoked.
//.Log QSO Window
image::log-qso.png[align="center",alt="Log QSO"]
* *Stop* will terminate normal data acquisition in case you want to
* *Stop* terminates normal data acquisition in case you want to
freeze the waterfall or open and explore a previously recorded audio
file.
* *Monitor* toggles normal receive operation on or off. This button
is highlighted in green when the _WSJT-X_ is receiving. If you are
is highlighted in green when _WSJT-X_ is receiving. If you are
using CAT control, toggling *Monitor* OFF relinquishes control of the
rig; if *Monitor returns to last used frequency* is selected on the
*Settings | General* tab, toggling *Monitor* back ON will return to
*File -> Settings -> General* tab, toggling *Monitor* back ON will return to
the original frequency.
* *Erase* clears the right-hand decoded text window.
@ -64,8 +62,9 @@ carrier at the specified Tx frequency (red marker on waterfall scale).
This process is useful for adjusting an antenna tuner or tuning an
amplifier. The button is highlighted in red while *Tune* is active.
Toggle the button a second time or click *Halt Tx* to terminate the
*Tune* process. Note that activating *Tune* interrupts a receive
sequence and will prevent decoding during that sequence.
*Tune* process.
TIP: Activating *Tune* interrupts a receive sequence and will prevent decoding during that sequence.
* Uncheck the box *Menus* to make the top-of-window menus disappear,
leaving more vertical space for decoded messages.

View File

@ -1,4 +1,4 @@
// Status=review
// Status=edited
Menus at top of the main window offer many options for configuration
and operation. Most of the items are self-explanatory; a few
@ -9,8 +9,7 @@ frequently used menu items are listed at the right edge of the menu.
image::MacAppMenu.png[align="left",alt="Mac App Menu"]
This menu appears on the Macintosh only. *Settings* appears here,
labeled as *Preferences*, rather than on the *File* menu. *About
WSJT-X* appears here rather than on the *Help* menu.
labeled as *Preferences*, rather than on the *File* menu. *About WSJT-X* appears here rather than on the *Help* menu.
[[FILE_MENU]]
==== File menu
@ -20,20 +19,12 @@ image::file-menu.png[align="left",alt="File Menu"]
==== Configuration Menu
image::config-menu.png[align="left",alt="File Menu"]
Most users of more than one mode prefer to create and use entries on
the *Configurations* menu for switching between modes. You can
*Clone* the configuration currently in use, *Rename* the clone as
desired, and then make all desired settings for the new configuration.
The easiest way is to start with a working setup for some mode, say
*FT8*. *Clone* it, then select *Configurations | FT8 - Copy | Rename
...*, enter a new name, say *FT4*, and click *OK*. Then select the
new name from the *Configurations* menu and choose *Switch To*. When
the new configuration comes up you can change any desired settings:
for example, select *FT4* from the *Mode* menu. Configurations save
all settings that are normally restored after a program restart,
including which of the defined configurations is currently active.
Many users prefer to create and use entries on the *Configurations*
menu for switching between modes. Simply *Clone* the *Default* entry,
*Rename* it as desired, and then make all desired settings for that
configuration. These settings are restored whenever you select that configuration.
As well as switching between configurations while running _WSJT-X_ you
As well as switching between configurations while running _WSJT-X_, you
can also start the application from the command line in any desired
configuration. Use the command-line option
`--config <configuration-name>`, or `-c` for short, as in these

View File

@ -1,4 +1,4 @@
// Status=review
// Status=edited
Two arrangements of controls are provided for generating and selecting
Tx messages. Controls familiar to users of program _WSJT_
@ -11,29 +11,27 @@ in one of the decoded text windows.
image::traditional-msg-box.png[align="center",alt="Traditional Message Menu"]
* Select the next message to be transmitted (at the start of your next
Tx sequence) by clicking on the circle under *Next*.
Tx sequence) by clicking the radio button in the *Next* column.
* To change to a specified Tx message immediately during a
transmission, click on a rectangular button under the *Now* label.
Changing a Tx message in mid-stream will slightly reduce the chance of
a correct decode, but it is usually OK if done in the first 10-20% of
a transmission.
transmission, click a rectangular button in the *Now* column.
Changing a Tx message in mid-stream slightly reduces the chance of
a correct decode, but it is usually OK if done in the first 10-20% of a transmission.
* All six Tx message fields are editable. You can modify an
automatically generated message or enter a desired message, keeping in
mind the limits on message content. See <<PROTOCOLS,Protocol
Specifications>> for details.
* Click on the pull-down arrow for message #5 to select one of the
pre-stored messages entered on the *Settings | Tx Macros* tab.
* Click the pull-down arrow for message #5 to select one of the
stored messages entered on the *Files -> Settings -> Tx Macros* tab.
Pressing *Enter* on a modified message #5 automatically adds that
message to the stored macros.
* In some circumstances it may be desirable to make your QSOs as
short as possible. To configure the program to start contacts with
message #2, disable message #1 by double-clicking on its round
radio-button or rectangular *Tx 1* button. Similarly, to send RR73
rather than RRR for message #4, double-click on one of its buttons.
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
rather than RRR for message #4, double-click one of its buttons.
The second arrangement of controls for generating and selecting
Tx messages appears on *Tab 2* of the Message Control Panel:
@ -52,12 +50,12 @@ immediately.
* You can enter and transmit anything (up to 13 characters, including
spaces) in the *Free Msg* box.
* Click on the pull-down arrow in the *Free Msg* box to select a
pre-stored macro. Pressing *Enter* on a modified message here
* 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.
+
TIP: During a transmission the actual message being sent always
appears in the first box of the status bar (bottom left of the main
appears in the first box of the status bar (bottom-left corner of the main
screen).

View File

@ -1,17 +1,16 @@
// Status=review
// Status=edited
Download and execute the package file {win32} (Win 7, Win 8, Win10,
32-bit) or {win64} (Win 7, Win 8, Win10, 64-bit) following these
instructions:
Download and execute the package file {win32} (WinXP, Vista, Win 7,
Win 8, Win10, 32-bit) or {win64} (Vista, Win 7, Win 8, Win10, 64-bit)
following these instructions:
* Install _WSJT-X_ into its own directory, for example `C:\WSJTX` or `
C:\WSJT\WSJTX`, rather than the conventional location `C:\Program
* Install _WSJT-X_ into its own directory, for example `C:\WSJTX` or `C:\WSJT\WSJTX`, rather than the conventional location `C:\Program
Files ...\WSJTX`.
* All program files relating to _WSJT-X_ will be stored in the chosen
* All program files relating to _WSJT-X_ are stored in the chosen
installation directory and its subdirectories.
* Logs and other writeable files will normally be found in the
* Logs and other writeable files are normally found in the
directory +
`C:\Users\<username>\AppData\Local\WSJT-X`.
@ -30,27 +29,23 @@ TIP: Your computer may be configured so that this directory is
[[OPENSSL]]
* _WSJT-X_ requires the _OpenSSL_ libraries to be installed, and
suitable libraries may already be installed on your system. If they
are not you will see this error shortly after requesting a fetch of
the latest LoTW users database. To fix this you need to install the
_OpenSSL_ libraries.
image:LoTW_TLS_error.png[_WSJT-X_ LoTW download TLS error,
align="center"]
* _WSJT-X_ requires installation of the _OpenSSL_ libraries. Suitable libraries may already be installed on your system. If they are not, you will see this error shortly after requesting a fetch of the latest LoTW users database. To fix this, install the _OpenSSL_ libraries.
image::LoTW_TLS_error.png[align="center"]
* You can download a suitable _OpenSSL_ package from
{win_openssl_packages}. You need the latest *Windows Light*
version. For the 32-bit _WSJT-X_ build use the latest Win32 v1.1.x
** You can download a suitable _OpenSSL_ package for Windows from
{win_openssl_packages}; you need the latest *Windows Light*
version. For the 32-bit _WSJT-X_ build, use the latest Win32 v1.1.1
version of the _OpenSSL_ libraries, for the 64-bit _WSJT-X_ use the
latest Win64 v1.1.x version of the _OpenSSL_ libraries which at the
time of writing were {win32_openssl} and {win64_openssl}. It is OK
to install both versions on a 64-bit system.
latest Win64 v1.1.1 version of the _OpenSSL_ libraries (Note: it is
OK to install both versions on a 64-bit system) which, at the time
of writing, were {win32_openssl} and {win64_openssl} respectively.
** Install the package and accept the default options, including the
option to copy the _OpenSSL_ DLLs to the Windows system
directory. There is no obligation to donate to the _OpenSSL_
project, un-check all the donation options if desired. +
project. Un-check all the donation options if desired. +
NOTE: If you still get the same network error after installing the
_OpenSSL_ libraries then you also need to install the
@ -61,21 +56,20 @@ NOTE: If you still get the same network error after installing the
TIP: If you cannot install the _OpenSSL_ libraries or do not have an
Internet connection on the computer used to run
_WSJT-X_&nbsp;{VERSION_MAJOR}.{VERSION_MINOR}, you can download
_WSJT-X_ {VERSION_MAJOR}.{VERSION_MINOR}, you can download
the _LoTW_ file manually. Go to
https://lotw.arrl.org/lotw-user-activity.csv in a web browser,
download the file, then move it to the _WSJT-X_ log files
directory. This directory can be opened by selecting
*File&nbsp;|&nbsp;Open&nbsp;log&nbsp;directory*.
*File|Open log directory* from the main menu.
* _WSJT-X_ expects your sound card to do its raw sampling at 48000 Hz.
To ensure that this will be so when running under recent versions of
Windows, open the system's *Sound* control panel and select in turn
the *Recording* and *Playback* tabs. Click on *Properties*, then
the *Recording* and *Playback* tabs. Click *Properties*, then
*Advanced*, and select *16 bit, 48000 Hz (DVD Quality)*. Switch off
all audio enhancement features for these devices.
* You can uninstall _WSJT-X_ by clicking its *Uninstall* link in the
Windows *Start* menu, or by using *Uninstall a Program* on the
Windows Control Panel Programs and Features option or in Settings
Apps and Features on Windows 10.
*Windows Control Panel|Programs and Features* option or in *Settings|Apps* on Windows 10.

View File

@ -1,5 +1,9 @@
#include "getfile.h"
#include <QDir>
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
#include <QRandomGenerator>
#include <random>
#endif
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
@ -171,6 +175,10 @@ void savewav(QString fname, int ntrperiod)
/* Generate gaussian random float with mean=0 and std_dev=1 */
float gran()
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
static std::normal_distribution<float> d;
return d (*QRandomGenerator::global ());
#else
float fac,rsq,v1,v2;
static float gset;
static int iset;
@ -192,6 +200,7 @@ float gran()
gset = v1*fac;
iset++;
return v2*fac;
#endif
}
int ptt(int nport, int ntx, int* iptt, int* nopen)

View File

@ -84,12 +84,12 @@ int killbyname(const char *szToTerminate)
if(hInstLib == NULL) return 605;
// Get procedure addresses.
lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))
lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))(void (*)())
GetProcAddress( hInstLib, "EnumProcesses" ) ;
lpfEnumProcessModules = (BOOL(WINAPI *)(HANDLE, HMODULE *,
DWORD, LPDWORD)) GetProcAddress( hInstLib, "EnumProcessModules" ) ;
DWORD, LPDWORD))(void (*)()) GetProcAddress( hInstLib, "EnumProcessModules" ) ;
lpfGetModuleBaseName =(DWORD (WINAPI *)(HANDLE, HMODULE, LPTSTR,
DWORD )) GetProcAddress( hInstLib, "GetModuleBaseNameA" ) ;
DWORD ))(void (*)()) GetProcAddress( hInstLib, "GetModuleBaseNameA" ) ;
if(lpfEnumProcesses == NULL || lpfEnumProcessModules == NULL ||
lpfGetModuleBaseName == NULL) {
@ -164,20 +164,20 @@ int killbyname(const char *szToTerminate)
// which does not have the Toolhelp32
// functions in the Kernel 32.
lpfCreateToolhelp32Snapshot=
(HANDLE(WINAPI *)(DWORD,DWORD))
(HANDLE(WINAPI *)(DWORD,DWORD))(void (*)())
GetProcAddress( hInstLib,
"CreateToolhelp32Snapshot" ) ;
lpfProcess32First=
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))(void (*)())
GetProcAddress( hInstLib, "Process32First" ) ;
lpfProcess32Next=
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))(void (*)())
GetProcAddress( hInstLib, "Process32Next" ) ;
lpfModule32First=
(BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
(BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))(void (*)())
GetProcAddress( hInstLib, "Module32First" ) ;
lpfModule32Next=
(BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))
(BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))(void (*)())
GetProcAddress( hInstLib, "Module32Next" ) ;
if( lpfProcess32Next == NULL ||
lpfProcess32First == NULL ||

View File

@ -196,7 +196,7 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
! the value of nrx is used to decide when mycall13 or dxcall13 should
! be used in place of a callsign from the hashtable
!
parameter (NSEC=84) !Number of ARRL Sections
parameter (NSEC=85) !Number of ARRL Sections
parameter (NUSCAN=65) !Number of US states and Canadian provinces
parameter (MAXGRID4=32400)
integer*8 n58
@ -228,7 +228,7 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
"ONS","OR ","ORG","PAC","PR ","QC ","RI ","SB ","SC ","SCV", &
"SD ","SDG","SF ","SFL","SJV","SK ","SNJ","STX","SV ","TN ", &
"UT ","VA ","VI ","VT ","WCF","WI ","WMA","WNY","WPA","WTX", &
"WV ","WWA","WY ","DX "/
"WV ","WWA","WY ","DX ","PE "/
data cmult/ &
"AL ","AK ","AZ ","AR ","CA ","CO ","CT ","DE ","FL ","GA ", &
"HI ","ID ","IL ","IN ","IA ","KS ","KY ","LA ","ME ","MD ", &
@ -281,7 +281,7 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
call unpacktext77(c77(1:71),msg(1:13))
msg(14:)=' '
msg=adjustl(msg)
else if(i3.eq.0 .and. n3.eq.1) then
! 0.1 K1ABC RR73; W9XYZ <KH1/KH7Z> -11 28 28 10 5 71 DXpedition Mode
read(c77,1010) n28a,n28b,n10,n5
@ -303,6 +303,9 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
n10.eq.hashmy10) call_3='<'//trim(mycall13)//'>'
msg=trim(call_1)//' RR73; '//trim(call_2)//' '//trim(call_3)//' '//crpt
else if(i3.eq.0 .and. n3.eq.2) then
unpk77_success=.false.
else if(i3.eq.0 .and. (n3.eq.3 .or. n3.eq.4)) then
! 0.3 WA9XYZ KA1ABC R 16A EMA 28 28 1 4 3 7 71 ARRL Field Day
! 0.4 WA9XYZ KA1ABC R 32A EMA 28 28 1 4 3 7 71 ARRL Field Day
@ -861,7 +864,7 @@ subroutine pack77_03(nwords,w,i3,n3,c77)
! Check 0.3 and 0.4 (ARRL Field Day exchange)
! Example message: WA9XYZ KA1ABC R 16A EMA 28 28 1 4 3 7 71
parameter (NSEC=84) !Number of ARRL Sections
parameter (NSEC=85) !Number of ARRL Sections
character*13 w(19)
character*77 c77
character*6 bcall_1,bcall_2
@ -876,7 +879,7 @@ subroutine pack77_03(nwords,w,i3,n3,c77)
"ONS","OR ","ORG","PAC","PR ","QC ","RI ","SB ","SC ","SCV", &
"SD ","SDG","SF ","SFL","SJV","SK ","SNJ","STX","SV ","TN ", &
"UT ","VA ","VI ","VT ","WCF","WI ","WMA","WNY","WPA","WTX", &
"WV ","WWA","WY ","DX "/
"WV ","WWA","WY ","DX ","PE "/
if(nwords.lt.4 .or. nwords.gt.5) return
call chkcall(w(1),bcall_1,ok1)

View File

@ -95,7 +95,6 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon, &
max_iterations=30
nharderrors=-1
nbadcrc=1 ! this is used upstream to flag good decodes.
fs2=12000.0/NDOWN
dt2=1.0/fs2
twopi=8.0*atan(1.0)
@ -403,14 +402,12 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon, &
dmin=0.0
norder=2
maxosd=2
if(ndepth.lt.3) maxosd=1
if(abs(nfqso-f1).le.napwid .or. abs(nftx-f1).le.napwid .or. ncontest.eq.7) then
if(ndepth.eq.1) maxosd=-1 ! BP only
if(ndepth.eq.2) maxosd=0 ! uncoupled BP+OSD
if(ndepth.eq.3 .and. &
(abs(nfqso-f1).le.napwid .or. abs(nftx-f1).le.napwid .or. ncontest.eq.7)) then
maxosd=2
endif
if(nagain) then
norder=3
maxosd=1
endif
call timer('dec174_91 ',0)
Keff=91
call decode174_91(llrz,Keff,maxosd,norder,apmask,message91,cw, &
@ -419,16 +416,16 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon, &
call timer('dec174_91 ',1)
msg37=' '
nbadcrc=1
if(nharderrors.lt.0 .or. nharderrors.gt.36) cycle
if(count(cw.eq.0).eq.174) cycle !Reject the all-zero codeword
write(c77,'(77i1)') message77
read(c77(72:74),'(b3)') n3
read(c77(75:77),'(b3)') i3
if(i3.gt.5 .or. (i3.eq.0.and.n3.gt.6)) cycle
if(i3.eq.0 .and. n3.eq.2) cycle
call unpack77(c77,1,msg37,unpk77_success)
if(.not.unpk77_success) then
cycle
endif
if(.not.unpk77_success) cycle
nbadcrc=0 ! If we get this far: valid codeword, valid (i3,n3), nonquirky message.
call get_ft8_tones_from_77bits(message77,itone)
if(lsubtract) then

View File

@ -45,7 +45,7 @@ subroutine gen_ft8wave(itone,nsym,nsps,bt,fsample,f0,cwave,wave,icmplx,nwave)
! Calculate and insert the audio waveform
phi=0.0
dphi = dphi + twopi*f0*dt !Shift frequency up by f0
wave=0.
if(icmplx .eq. 0) wave=0.
if(icmplx .ne. 0) cwave=0. !Avoid writing to memory we may not have access to
call timer('gen_loop',0)

View File

@ -71,7 +71,16 @@ contains
write(datetime,1001) nutc !### TEMPORARY ###
1001 format("000000_",i6.6)
if(ndepth.eq.1 .and. nzhsym.lt.50) then
ndec_early=0
return
endif
if(ndepth.eq.1 .and. nzhsym.eq.50) then
dd=iwave
endif
call ft8apset(mycall12,hiscall12,ncontest,apsym2,aph10)
if(nzhsym.le.47) then
dd=iwave
dd1=dd
@ -128,10 +137,11 @@ contains
endif
! For now:
! ndepth=1: subtraction, 3 passes, bp (no subtract refinement)
! ndepth=1: 1 pass, bp
! ndepth=2: subtraction, 3 passes, bp+osd (no subtract refinement)
! ndepth=3: subtraction, 3 passes, bp+osd
npass=3
if(ndepth.eq.1) npass=1
do ipass=1,npass
newdat=.true.
syncmin=1.3
@ -148,7 +158,7 @@ contains
elseif(ipass.eq.3) then
if((ndecodes-n2).eq.0) cycle
lsubtract=.true.
ndeep=3
ndeep=ndepth
endif
call timer('sync8 ',0)
maxc=MAXCAND

View File

@ -442,9 +442,21 @@ bool WorkedBefore::add (QString const& call
QTextStream out {&file};
if (!file.size ())
{
out << "WSJT-X ADIF Export<eoh>" << endl; // new file
out << "WSJT-X ADIF Export<eh>" << // new file
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
endl
#else
Qt::endl
#endif
;
}
out << ADIF_record << " <eor>" << endl;
out << ADIF_record << " <eor>" <<
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
endl
#else
Qt::endl
#endif
;
}
m_->worked_.emplace (call.toUpper (), grid.left (4).toUpper (), band.toUpper (), mode.toUpper ()
, entity.entity_name, entity.continent, entity.CQ_zone, entity.ITU_zone);

View File

@ -103,7 +103,13 @@ QByteArray LogBook::QSOToADIF (QString const& hisCall, QString const& hisGrid, Q
if(operator_call!="") t+=" <operator:" + QString::number(operator_call.size()) + ">" + operator_call;
if (xSent.size ())
{
auto words = xSent.split (' ', QString::SkipEmptyParts);
auto words = xSent.split (' '
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
, QString::SkipEmptyParts
#else
, Qt::SkipEmptyParts
#endif
);
if (words.size () > 1)
{
if (words.back ().toUInt ())
@ -126,7 +132,13 @@ QByteArray LogBook::QSOToADIF (QString const& hisCall, QString const& hisGrid, Q
}
}
if (xRcvd.size ()) {
auto words = xRcvd.split (' ', QString::SkipEmptyParts);
auto words = xRcvd.split (' '
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
, QString::SkipEmptyParts
#else
, Qt::SkipEmptyParts
#endif
);
if (words.size () == 2)
{
if (words.at (1).toUInt ())

View File

@ -49,6 +49,7 @@ extern "C" {
namespace
{
#if QT_VERSION < QT_VERSION_CHECK (5, 15, 0)
struct RNGSetup
{
RNGSetup ()
@ -58,6 +59,7 @@ namespace
qsrand (seed); // this is good for rand() as well
}
} seeding;
#endif
// We can't use the GUI after QApplication::exit() is called so
// uncaught exceptions can get lost on Windows systems where there

View File

@ -274,5 +274,9 @@ void FoxLog::export_qsos (QTextStream& out) const
<< ADIF_field {"operator", m_->configuration_->opCall ()}
<< "<eor>";
}
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
out << endl;
#else
out << Qt::endl;
#endif
}

View File

@ -4766,7 +4766,7 @@ Qt::Alignment QCPLayoutInset::insetAlignment(int index) const
else
{
qDebug() << Q_FUNC_INFO << "Invalid element index:" << index;
return 0;
return Qt::Alignment {};
}
}
@ -6013,11 +6013,13 @@ double QCPAxisTickerDateTime::dateTimeToKey(const QDateTime dateTime)
*/
double QCPAxisTickerDateTime::dateTimeToKey(const QDate date)
{
# if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
#if QT_VERSION < QT_VERSION_CHECK(4, 7, 0)
return QDateTime(date).toTime_t();
# else
#elif QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
return QDateTime(date).toMSecsSinceEpoch()/1000.0;
# endif
#else
return date.startOfDay().toMSecsSinceEpoch()/1000.0;
#endif
}
/* end of 'src/axis/axistickerdatetime.cpp' */
@ -6499,7 +6501,11 @@ void QCPAxisTickerText::addTick(double position, QString label)
*/
void QCPAxisTickerText::addTicks(const QMap<double, QString> &ticks)
{
# if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
mTicks.unite(ticks);
#else
mTicks.insert(ticks);
#endif
}
/*! \overload
@ -12598,9 +12604,11 @@ QCustomPlot::QCustomPlot(QWidget *parent) :
mBufferDevicePixelRatio(1.0), // will be adapted to primary screen below
mPlotLayout(0),
mAutoAddPlottableToLegend(true),
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
mAntialiasedElements(QCP::aeNone),
mNotAntialiasedElements(QCP::aeNone),
mInteractions(0),
#endif
mSelectionTolerance(8),
mNoAntialiasingOnDrag(false),
mBackgroundBrush(Qt::white, Qt::SolidPattern),
@ -12617,7 +12625,9 @@ QCustomPlot::QCustomPlot(QWidget *parent) :
mReplotting(false),
mReplotQueued(false),
mOpenGlMultisamples(16),
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
mOpenGlAntialiasedElementsBackup(QCP::aeNone),
#endif
mOpenGlCacheLabelsBackup(true)
{
setAttribute(Qt::WA_NoMousePropagation);
@ -14668,7 +14678,15 @@ void QCustomPlot::wheelEvent(QWheelEvent *event)
{
emit mouseWheel(event);
// forward event to layerable under cursor:
QList<QCPLayerable*> candidates = layerableListAt(event->pos(), false);
QList<QCPLayerable*> candidates = layerableListAt(
#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
event->pos()
#elif QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
event->posF()
#else
event->position()
#endif
, false);
for (int i=0; i<candidates.size(); ++i)
{
event->accept(); // default impl of QCPLayerable's mouse events ignore the event, in that case propagate to next candidate in list
@ -15002,7 +15020,7 @@ void QCustomPlot::processRectSelection(QRect rect, QMouseEvent *event)
if (mInteractions.testFlag(QCP::iSelectPlottables))
{
QMap<int, QPair<QCPAbstractPlottable*, QCPDataSelection> > potentialSelections; // map key is number of selected data points, so we have selections sorted by size
QMultiMap<int, QPair<QCPAbstractPlottable*, QCPDataSelection> > potentialSelections; // map key is number of selected data points, so we have selections sorted by size
QRectF rectF(rect.normalized());
if (QCPAxisRect *affectedAxisRect = axisRectAt(rectF.topLeft()))
{
@ -15013,7 +15031,7 @@ void QCustomPlot::processRectSelection(QRect rect, QMouseEvent *event)
{
QCPDataSelection dataSel = plottableInterface->selectTestRect(rectF, true);
if (!dataSel.isEmpty())
potentialSelections.insertMulti(dataSel.dataPointCount(), QPair<QCPAbstractPlottable*, QCPDataSelection>(plottable, dataSel));
potentialSelections.insert(dataSel.dataPointCount(), QPair<QCPAbstractPlottable*, QCPDataSelection>(plottable, dataSel));
}
}
@ -15022,7 +15040,7 @@ void QCustomPlot::processRectSelection(QRect rect, QMouseEvent *event)
// only leave plottable with most selected points in map, since we will only select a single plottable:
if (!potentialSelections.isEmpty())
{
QMap<int, QPair<QCPAbstractPlottable*, QCPDataSelection> >::iterator it = potentialSelections.begin();
QMultiMap<int, QPair<QCPAbstractPlottable*, QCPDataSelection> >::iterator it = potentialSelections.begin();
while (it != potentialSelections.end()-1) // erase all except last element
it = potentialSelections.erase(it);
}
@ -15048,7 +15066,7 @@ void QCustomPlot::processRectSelection(QRect rect, QMouseEvent *event)
}
// go through selections in reverse (largest selection first) and emit select events:
QMap<int, QPair<QCPAbstractPlottable*, QCPDataSelection> >::const_iterator it = potentialSelections.constEnd();
QMultiMap<int, QPair<QCPAbstractPlottable*, QCPDataSelection> >::const_iterator it = potentialSelections.constEnd();
while (it != potentialSelections.constBegin())
{
--it;
@ -17619,14 +17637,24 @@ void QCPAxisRect::wheelEvent(QWheelEvent *event)
if (mRangeZoom != 0)
{
double factor;
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
double wheelSteps = event->delta()/120.0; // a single step delta is +/-120 usually
#else
double wheelSteps = event->angleDelta().y()/120.0; // a single step delta is +/-120 usually
#endif
if (mRangeZoom.testFlag(Qt::Horizontal))
{
factor = qPow(mRangeZoomFactorHorz, wheelSteps);
for (int i=0; i<mRangeZoomHorzAxis.size(); ++i)
{
if (!mRangeZoomHorzAxis.at(i).isNull())
mRangeZoomHorzAxis.at(i)->scaleRange(factor, mRangeZoomHorzAxis.at(i)->pixelToCoord(event->pos().x()));
mRangeZoomHorzAxis.at(i)->scaleRange(factor, mRangeZoomHorzAxis.at(i)->pixelToCoord(
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
event->posF().x()
#else
event->position().x()
#endif
));
}
}
if (mRangeZoom.testFlag(Qt::Vertical))
@ -17635,7 +17663,13 @@ void QCPAxisRect::wheelEvent(QWheelEvent *event)
for (int i=0; i<mRangeZoomVertAxis.size(); ++i)
{
if (!mRangeZoomVertAxis.at(i).isNull())
mRangeZoomVertAxis.at(i)->scaleRange(factor, mRangeZoomVertAxis.at(i)->pixelToCoord(event->pos().y()));
mRangeZoomVertAxis.at(i)->scaleRange(factor, mRangeZoomVertAxis.at(i)->pixelToCoord(
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
event->posF().y()
#else
event->position().y()
#endif
));
}
}
mParentPlot->replot();
@ -19262,7 +19296,7 @@ void QCPColorScale::setRangeDrag(bool enabled)
if (enabled)
mAxisRect.data()->setRangeDrag(QCPAxis::orientation(mType));
else
mAxisRect.data()->setRangeDrag(0);
mAxisRect.data()->setRangeDrag(Qt::Orientations());
}
/*!
@ -19282,7 +19316,7 @@ void QCPColorScale::setRangeZoom(bool enabled)
if (enabled)
mAxisRect.data()->setRangeZoom(QCPAxis::orientation(mType));
else
mAxisRect.data()->setRangeZoom(0);
mAxisRect.data()->setRangeZoom(Qt::Orientations());
}
/*!

View File

@ -51,6 +51,12 @@
return QString {mo.enumerator (mo.indexOfEnumerator (#ENUM)).valueToKey (static_cast<int> (m))}; \
}
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
Qt::SplitBehaviorFlags const SkipEmptyParts = Qt::SkipEmptyParts;
#else
QString::SplitBehavior const SkipEmptyParts = QString::SkipEmptyParts;
#endif
inline
void throw_qstring (QString const& qs)
{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -891,12 +891,12 @@ Format:
<message>
<location filename="../SampleDownloader/Directory.cpp" line="51"/>
<source>File</source>
<translation></translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../SampleDownloader/Directory.cpp" line="51"/>
<source>Progress</source>
<translation></translation>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../SampleDownloader/Directory.cpp" line="113"/>
@ -1079,10 +1079,6 @@ Error: %2 - %3</source>
<source>Freq (Hz)</source>
<translation>(Hz)</translation>
</message>
<message>
<source>Phase (Î )</source>
<translation type="vanished"> (Î )</translation>
</message>
<message>
<location filename="../EqualizationToolsDialog.cpp" line="309"/>
<source>Phase (Π)</source>
@ -2179,7 +2175,7 @@ Yellow when too low</source>
<message>
<location filename="../widgets/mainwindow.ui" line="904"/>
<source> Pwr</source>
<translation> </translation>
<translation> </translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="914"/>
@ -2258,6 +2254,11 @@ Yellow when too low</source>
<source>Set Tx frequency to Rx Frequency</source>
<translation></translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1139"/>
<source></source>
<translation></translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1146"/>
<source>Frequency tolerance (Hz)</source>
@ -2273,11 +2274,6 @@ Yellow when too low</source>
<source>Set Rx frequency to Tx Frequency</source>
<translation></translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1139"/>
<source></source>
<translation></translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1189"/>
<source></source>
@ -2414,7 +2410,7 @@ Not available to nonstandard callsign holders.</source>
<message>
<location filename="../widgets/mainwindow.ui" line="1349"/>
<source>Rx All Freqs</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="1358"/>
@ -2973,12 +2969,12 @@ ENTERを押してテキストを登録リストに追加.
<message>
<location filename="../widgets/mainwindow.ui" line="2342"/>
<source>N List </source>
<translation>Nリスト </translation>
<translation> </translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="2373"/>
<source>N Slots </source>
<translation>Nスロット </translation>
<translation> </translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="2404"/>
@ -3004,8 +3000,8 @@ ENTERを押してテキストを登録リストに追加.
<message>
<location filename="../widgets/mainwindow.ui" line="2452"/>
<source>More CQs</source>
<translatorcomment></translatorcomment>
<translation type="unfinished"></translation>
<translatorcomment>51CQを出す</translatorcomment>
<translation></translation>
</message>
<message>
<location filename="../widgets/mainwindow.ui" line="2577"/>
@ -4030,7 +4026,7 @@ UDPサーバー %2:%3</translation>
<message>
<location filename="../widgets/messageaveraging.ui" line="29"/>
<source> UTC Sync DT Freq </source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
</context>
<context>
@ -4172,6 +4168,7 @@ UDPサーバー %2:%3</translation>
<context>
<name>QObject</name>
<message>
<location filename="../main.cpp" line="340"/>
<source>Invalid rig name - \ &amp; / not allowed</source>
<translation type="vanished"> \ &amp; / 使</translation>
</message>
@ -4336,7 +4333,7 @@ Error(%2): %3</source>
<message>
<location filename="../SampleDownloader.cpp" line="114"/>
<source>Check this is you get SSL/TLS errors</source>
<translation type="unfinished"></translation>
<translation>SSL/TLSエラーを表示</translation>
</message>
<message>
<location filename="../SampleDownloader.cpp" line="132"/>
@ -4615,7 +4612,7 @@ Error(%2): %3</source>
<location filename="../widgets/widegraph.ui" line="247"/>
<source>Ref Spec</source>
<translatorcomment></translatorcomment>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../widgets/widegraph.ui" line="259"/>
@ -4899,7 +4896,7 @@ Error(%2): %3</source>
<message>
<location filename="../Configuration.ui" line="301"/>
<source>Behavior</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../Configuration.ui" line="307"/>
@ -5328,7 +5325,7 @@ or bandwidth is selected).</source>
<message>
<location filename="../Configuration.ui" line="1083"/>
<source>If this is available then it is usually the correct mode for this program.</source>
<translation type="unfinished"></translation>
<translation>使.</translation>
</message>
<message>
<location filename="../Configuration.ui" line="1086"/>
@ -6214,92 +6211,114 @@ Right click for insert and delete options.</source>
<name>main</name>
<message>
<location filename="../main.cpp" line="83"/>
<location filename="../main.cpp" line="408"/>
<location filename="../main.cpp" line="563"/>
<source>Fatal error</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="88"/>
<location filename="../main.cpp" line="413"/>
<location filename="../main.cpp" line="568"/>
<source>Unexpected fatal error</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="194"/>
<source>Where &lt;rig-name&gt; is for multi-instance support.</source>
<translation type="vanished">&lt;rig-name&gt;.</translation>
</message>
<message>
<location filename="../main.cpp" line="195"/>
<source>rig-name</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="200"/>
<source>Where &lt;configuration&gt; is an existing one.</source>
<translation type="vanished">&lt;configuration&gt;.</translation>
</message>
<message>
<source>Where &lt;language&gt; is &lt;lang-code&gt;[-&lt;country-code&gt;].</source>
<translation type="vanished">&lt;language&gt;&lt;lang-code&gt;[-&lt;country-code&gt;].</translation>
<location filename="../main.cpp" line="201"/>
<source>configuration</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="206"/>
<source>Where &lt;language&gt; is &lt;lang-code&gt;[-&lt;country-code&gt;].</source>
<translation> &lt;language&gt; &lt;lang-code&gt;[-&lt;country-code&gt;].</translation>
</message>
<message>
<location filename="../main.cpp" line="207"/>
<source>language</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="211"/>
<source>Writable files in test location. Use with caution, for testing only.</source>
<translation type="vanished">. 使.</translation>
</message>
<message>
<location filename="../main.cpp" line="216"/>
<source>Command line error</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../main.cpp" line="223"/>
<source>Command line help</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../main.cpp" line="228"/>
<source>Application version</source>
<translation type="vanished"></translation>
</message>
<message>
<location filename="../main.cpp" line="223"/>
<location filename="../main.cpp" line="371"/>
<source>Another instance may be running</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="224"/>
<location filename="../main.cpp" line="372"/>
<source>try to remove stale lock file?</source>
<translation>?</translation>
</message>
<message>
<location filename="../main.cpp" line="259"/>
<location filename="../main.cpp" line="414"/>
<source>Failed to create a temporary directory</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="260"/>
<location filename="../main.cpp" line="268"/>
<location filename="../main.cpp" line="415"/>
<location filename="../main.cpp" line="423"/>
<source>Path: &quot;%1&quot;</source>
<translation>:&quot;%1&quot;</translation>
</message>
<message>
<location filename="../main.cpp" line="266"/>
<location filename="../main.cpp" line="421"/>
<source>Failed to create a usable temporary directory</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="267"/>
<location filename="../main.cpp" line="422"/>
<source>Another application may be locking the directory</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="300"/>
<location filename="../main.cpp" line="455"/>
<source>Failed to create data directory</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="301"/>
<location filename="../main.cpp" line="456"/>
<source>path: &quot;%1&quot;</source>
<translation>: &quot;%1&quot;</translation>
</message>
<message>
<location filename="../main.cpp" line="356"/>
<location filename="../main.cpp" line="511"/>
<source>Shared memory error</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="357"/>
<location filename="../main.cpp" line="512"/>
<source>Unable to create shared memory segment</source>
<translation></translation>
</message>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -99,7 +99,13 @@ void ExportCabrillo::save_log ()
<< "ADDRESS: " << ui->addr_1_line_edit->text() << '\n'
<< "ADDRESS: " << ui->addr_2_line_edit->text() << '\n';
if (log_) log_->export_qsos (out);
out << "END-OF-LOG:" << endl;
out << "END-OF-LOG:"
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
return;
} else {
auto const& message = tr ("Cannot open \"%1\" for writing: %2")

View File

@ -131,7 +131,11 @@ auto Astro::astroUpdate(QDateTime const& t, QString const& mygrid, QString const
QTextStream out {&message};
out << " " << date << "\n"
"UTC: " << utc << "\n"
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
<< Qt::fixed
#else
<< fixed
#endif
<< qSetFieldWidth (6)
<< qSetRealNumberPrecision (1)
<< "Az: " << azmoon << "\n"

View File

@ -142,8 +142,20 @@ void LogQSO::accept()
}
if ((special_op == SpOp::RTTY and xsent!="" and xrcvd!="")) {
if(rptSent=="" or !xsent.contains(rptSent+" ")) rptSent=xsent.split(" ",QString::SkipEmptyParts).at(0);
if(rptRcvd=="" or !xrcvd.contains(rptRcvd+" ")) rptRcvd=xrcvd.split(" ",QString::SkipEmptyParts).at(0);
if(rptSent=="" or !xsent.contains(rptSent+" ")) rptSent=xsent.split(" "
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
, QString::SkipEmptyParts
#else
, Qt::SkipEmptyParts
#endif
).at(0);
if(rptRcvd=="" or !xrcvd.contains(rptRcvd+" ")) rptRcvd=xrcvd.split(" "
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
, QString::SkipEmptyParts
#else
, Qt::SkipEmptyParts
#endif
).at(0);
}
// validate
@ -181,7 +193,13 @@ void LogQSO::accept()
"," + rptSent + "," + rptRcvd + "," + m_txPower +
"," + m_comments + "," + name;
QTextStream out(&f);
out << logEntry << endl;
out << logEntry <<
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
endl
#else
Qt::endl
#endif
;
f.close();
}

View File

@ -39,6 +39,9 @@
#include <QUdpSocket>
#include <QAbstractItemView>
#include <QInputDialog>
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
#include <QRandomGenerator>
#endif
#include "revision_utils.hpp"
#include "qt_helpers.hpp"
@ -84,7 +87,6 @@
#include "ui_mainwindow.h"
#include "moc_mainwindow.cpp"
extern "C" {
//----------------------------------------------------- C and Fortran routines
void symspec_(struct dec_data *, int* k, int* ntrperiod, int* nsps, int* ingain,
@ -654,16 +656,17 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
subProcessError (&proc_jt9, error);
});
#else
connect(&proc_jt9, static_cast<void (QProcess::*) (QProcess::ProcessError)> (&QProcess::errorOccurred),
[this] (QProcess::ProcessError error) {
subProcessError (&proc_jt9, error);
});
connect(&proc_jt9, &QProcess::errorOccurred, [this] (QProcess::ProcessError error) {
subProcessError (&proc_jt9, error);
});
#endif
connect(&proc_jt9, static_cast<void (QProcess::*) (int, QProcess::ExitStatus)> (&QProcess::finished),
[this] (int exitCode, QProcess::ExitStatus status) {
subProcessFailed (&proc_jt9, exitCode, status);
});
connect(&p1, &QProcess::started, [this] () {
showStatusMessage (QString {"Started: %1 \"%2\""}.arg (p1.program ()).arg (p1.arguments ().join (QLatin1String {"\" \""})));
});
connect(&p1, &QProcess::readyReadStandardOutput, this, &MainWindow::p1ReadFromStdout);
#if QT_VERSION < QT_VERSION_CHECK (5, 6, 0)
connect(&p1, static_cast<void (QProcess::*) (QProcess::ProcessError)> (&QProcess::error),
@ -671,10 +674,9 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
subProcessError (&p1, error);
});
#else
connect(&p1, static_cast<void (QProcess::*) (QProcess::ProcessError)> (&QProcess::errorOccurred),
[this] (QProcess::ProcessError error) {
subProcessError (&p1, error);
});
connect(&p1, &QProcess::errorOccurred, [this] (QProcess::ProcessError error) {
subProcessError (&p1, error);
});
#endif
connect(&p1, static_cast<void (QProcess::*) (int, QProcess::ExitStatus)> (&QProcess::finished),
[this] (int exitCode, QProcess::ExitStatus status) {
@ -687,11 +689,13 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
subProcessError (&p3, error);
});
#else
connect(&p3, static_cast<void (QProcess::*) (QProcess::ProcessError)> (&QProcess::errorOccurred),
[this] (QProcess::ProcessError error) {
subProcessError (&p3, error);
});
connect(&p3, &QProcess::errorOccurred, [this] (QProcess::ProcessError error) {
subProcessError (&p3, error);
});
#endif
connect(&p3, &QProcess::started, [this] () {
showStatusMessage (QString {"Started: %1 \"%2\""}.arg (p3.program ()).arg (p3.arguments ().join (QLatin1String {"\" \""})));
});
connect(&p3, static_cast<void (QProcess::*) (int, QProcess::ExitStatus)> (&QProcess::finished),
[this] (int exitCode, QProcess::ExitStatus status) {
subProcessFailed (&p3, exitCode, status);
@ -1400,7 +1404,13 @@ void MainWindow::dataSink(qint64 frames)
QFile f {m_config.writeable_data_dir ().absoluteFilePath ("fmt.all")};
if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
QTextStream out(&f);
out << t << endl;
out << t
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
f.close();
} else {
MessageBox::warning_message (this, tr ("File Open Error")
@ -1507,36 +1517,39 @@ void MainWindow::dataSink(qint64 frames)
}
if(m_mode.startsWith ("WSPR")) {
QString t2,cmnd,depth_string;
double f0m1500=m_dialFreqRxWSPR/1000000.0; // + 0.000001*(m_BFO - 1500);
t2 = t2.asprintf(" -f %.6f ",f0m1500);
if((m_ndepth&7)==1) depth_string=" -qB "; //2 pass w subtract, no Block detection, no shift jittering
if((m_ndepth&7)==2) depth_string=" -C 500 -o 4 "; //3 pass, subtract, Block detection, OSD
if((m_ndepth&7)==3) depth_string=" -C 500 -o 4 -d "; //3 pass, subtract, Block detect, OSD, more candidates
QString degrade;
degrade = degrade.asprintf("-d %4.1f ",m_config.degrade());
QStringList t2;
QStringList depth_args;
t2 << "-f" << QString {"%1"}.arg (m_dialFreqRxWSPR / 1000000.0, 0, 'f', 6);
if((m_ndepth&7)==1) depth_args << "-qB"; //2 pass w subtract, no Block detection, no shift jittering
if((m_ndepth&7)==2) depth_args << "-C" << "500" << "-o" << "4"; //3 pass, subtract, Block detection, OSD
if((m_ndepth&7)==3) depth_args << "-C" << "500" << "-o" << "4" << "-d"; //3 pass, subtract, Block detect, OSD, more candidates
QStringList degrade;
degrade << "-d" << QString {"%1"}.arg (m_config.degrade(), 4, 'f', 1);
m_cmndP1.clear ();
if(m_diskData) {
cmnd='"' + m_appDir + '"' + "/wsprd " + depth_string + " -a \"" +
QDir::toNativeSeparators(m_config.writeable_data_dir ().absolutePath()) + "\" \"" + m_path + "\"";
m_cmndP1 << depth_args << "-a"
<< QDir::toNativeSeparators (m_config.writeable_data_dir ().absolutePath()) << m_path;
} else {
if(m_mode=="WSPR-LF") {
// cmnd='"' + m_appDir + '"' + "/wspr_fsk8d " + degrade + t2 +" -a \"" +
// QDir::toNativeSeparators(m_config.writeable_data_dir ().absolutePath()) + "\" " +
// '"' + m_fnameWE + ".wav\"";
} else {
cmnd='"' + m_appDir + '"' + "/wsprd " + depth_string + " -a \"" +
QDir::toNativeSeparators(m_config.writeable_data_dir ().absolutePath()) + "\" " +
t2 + '"' + m_fnameWE + ".wav\"";
}
// if(m_mode=="WSPR-LF")
// {
// m_cmndP1 << degrade << t2 << "-a"
// << QDir::toNativeSeparators (m_config.writeable_data_dir ().absolutePath())
// << m_fnameWE + ".wav";
// }
// else
{
m_cmndP1 << depth_args << "-a"
<< QDir::toNativeSeparators (m_config.writeable_data_dir ().absolutePath())
<< t2 << m_fnameWE + ".wav";
}
}
QString t3=cmnd;
int i1=cmnd.indexOf("/wsprd ");
cmnd=t3.mid(0,i1+7) + t3.mid(i1+7);
// QString t3=cmnd;
// int i1=cmnd.indexOf("/wsprd ");
// cmnd=t3.mid(0,i1+7) + t3.mid(i1+7);
// if(m_mode=="WSPR-LF") cmnd=cmnd.replace("/wsprd ","/wspr_fsk8d "+degrade+t2);
if (ui) ui->DecodeButton->setChecked (true);
m_cmndP1=QDir::toNativeSeparators(cmnd);
// m_cmndP1=QDir::toNativeSeparators(cmnd);
p1Timer.start(1000);
m_decoderBusy = true;
statusUpdate ();
@ -1547,7 +1560,14 @@ void MainWindow::dataSink(qint64 frames)
void MainWindow::startP1()
{
p1.start(m_cmndP1);
// if (m_mode=="WSPR-LF")
// {
// p1.start (QDir::toNativeSeparators (QDir {QApplication::applicationDirPath ()}.absoluteFilePath ("wspr_fsk8d")), m_cmndP1);
// }
// else
{
p1.start (QDir::toNativeSeparators (QDir {QApplication::applicationDirPath ()}.absoluteFilePath ("wsprd")), m_cmndP1);
}
}
QString MainWindow::save_wave_file (QString const& name, short const * data, int samples,
@ -2066,7 +2086,7 @@ void MainWindow::keyPressEvent (QKeyEvent * e)
break;
case Qt::Key_L:
if(e->modifiers() & Qt::ControlModifier) {
lookup(true);
lookup();
genStdMsgs(m_rpt);
return;
}
@ -2184,7 +2204,13 @@ void MainWindow::statusChanged()
if (!tmpGrid.size ()) tmpGrid="n/a"; // Not Available
out << qSetRealNumberPrecision (12) << (m_freqNominal / 1.e6)
<< ";" << m_mode << ";" << m_hisCall << ";"
<< ui->rptSpinBox->value() << ";" << m_modeTx << ";" << tmpGrid << endl;
<< ui->rptSpinBox->value() << ";" << m_modeTx << ";" << tmpGrid
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
f.close();
} else {
if (m_splash && m_splash->isVisible ()) m_splash->hide ();
@ -2851,7 +2877,13 @@ void MainWindow::decode() //decode()
if( m_dateTimeLastTX.isValid () ) {
qint64 isecs_since_tx = m_dateTimeLastTX.secsTo(now);
dec_data.params.lapcqonly= (isecs_since_tx > 300);
// QTextStream(stdout) << "last tx " << isecs_since_tx << endl;
// QTextStream(stdout) << "last tx " << isecs_since_tx
// #if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
// << Qt::endl
// #else
// << endl
// #endif
// ;
} else {
m_dateTimeLastTX = now.addSecs(-900);
dec_data.params.lapcqonly=true;
@ -3240,7 +3272,7 @@ void MainWindow::readFromStdout() //readFromStdout
int audioFreq=decodedtext.frequencyOffset();
if(m_mode=="FT8" or m_mode=="FT4") {
auto const& parts = decodedtext.string().remove("<").remove(">")
.split (' ', QString::SkipEmptyParts);
.split (' ', SkipEmptyParts);
if (parts.size() > 6) {
auto for_us = parts[5].contains (m_baseCall)
|| ("DE" == parts[5] && qAbs (ui->RxFreqSpinBox->value () - audioFreq) <= 10);
@ -3280,7 +3312,7 @@ void MainWindow::readFromStdout() //readFromStdout
if(m_mode=="FT8" and SpecOp::HOUND==m_config.special_op_id()) {
if(decodedtext.string().contains(";")) {
QStringList w=decodedtext.string().mid(24).split(" ",QString::SkipEmptyParts);
QStringList w=decodedtext.string().mid(24).split(" ",SkipEmptyParts);
QString foxCall=w.at(3);
foxCall=foxCall.remove("<").remove(">");
if(w.at(0)==m_config.my_callsign() or w.at(0)==Radio::base_callsign(m_config.my_callsign())) {
@ -3296,7 +3328,7 @@ void MainWindow::readFromStdout() //readFromStdout
hound_reply ();
}
} else {
QStringList w=decodedtext.string().mid(24).split(" ",QString::SkipEmptyParts);
QStringList w=decodedtext.string().mid(24).split(" ",SkipEmptyParts);
if(decodedtext.string().contains("/")) w.append(" +00"); //Add a dummy report
if(w.size()>=3) {
QString foxCall=w.at(1);
@ -3384,7 +3416,7 @@ void MainWindow::auto_sequence (DecodedText const& message, unsigned start_toler
|| message_words.contains ("DE")))
|| !message.isStandardMessage ()); // free text 73/RR73
QStringList w=message.string().mid(22).remove("<").remove(">").split(" ",QString::SkipEmptyParts);
QStringList w=message.string().mid(22).remove("<").remove(">").split(" ",SkipEmptyParts);
QString w2;
int nrpt=0;
if (w.size () > 2)
@ -3665,8 +3697,12 @@ void MainWindow::guiUpdate()
else if (SpecOp::HOUND == m_config.special_op_id()) {
if(m_auto && !m_tune) {
if (ui->TxFreqSpinBox->value() < 999 && m_ntx != 3) {
int nf = (qrand() % 2000) + 1000; // Hound randomized range: 1000-3000 Hz
ui->TxFreqSpinBox->setValue(nf);
// Hound randomized range: 1000-3000 Hz
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
ui->TxFreqSpinBox->setValue (QRandomGenerator::global ()->bounded (1000, 2999));
#else
ui->TxFreqSpinBox->setValue ((qrand () % 2000) + 1000);
#endif
}
}
if (m_nSentFoxRrpt==2 and m_ntx==3) {
@ -3685,8 +3721,11 @@ void MainWindow::guiUpdate()
// If HoldTxFreq is not checked, randomize Fox's Tx Freq
// NB: Maybe this should be done no more than once every 5 minutes or so ?
if(m_mode=="FT8" and SpecOp::FOX==m_config.special_op_id() and !ui->cbHoldTxFreq->isChecked()) {
int fTx = 300.0 + 300.0*double(qrand())/RAND_MAX;
ui->TxFreqSpinBox->setValue(fTx);
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
ui->TxFreqSpinBox->setValue (QRandomGenerator::global ()->bounded (300, 599));
#else
ui->TxFreqSpinBox->setValue(300.0 + 300.0*double(qrand())/RAND_MAX);
#endif
}
setXIT (ui->TxFreqSpinBox->value ());
@ -3858,7 +3897,7 @@ void MainWindow::guiUpdate()
if(SpecOp::FIELD_DAY==m_config.special_op_id() or SpecOp::RTTY==m_config.special_op_id()) {
if(m_ntx==2 or m_ntx==3) {
QStringList t=ui->tx2->text().split(' ', QString::SkipEmptyParts);
QStringList t=ui->tx2->text().split(' ', SkipEmptyParts);
int n=t.size();
m_xSent=t.at(n-2) + " " + t.at(n-1);
}
@ -3893,7 +3932,7 @@ void MainWindow::guiUpdate()
auto t2 = QDateTime::currentDateTimeUtc ().toString ("hhmm");
icw[0] = 0;
auto msg_parts = m_currentMessage.split (' ', QString::SkipEmptyParts);
auto msg_parts = m_currentMessage.split (' ', SkipEmptyParts);
if (msg_parts.size () > 2) {
// clean up short code forms
msg_parts[0].remove (QChar {'<'});
@ -3904,7 +3943,7 @@ void MainWindow::guiUpdate()
auto is_73 = m_QSOProgress >= ROGER_REPORT
&& message_is_73 (m_currentMessageType, msg_parts);
m_sentFirst73 = is_73
&& !message_is_73 (m_lastMessageType, m_lastMessageSent.split (' ', QString::SkipEmptyParts));
&& !message_is_73 (m_lastMessageType, m_lastMessageSent.split (' ', SkipEmptyParts));
if (m_sentFirst73) {
m_qsoStop=t2;
if(m_config.id_after_73 ()) {
@ -4472,7 +4511,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
auto ctrl = modifiers.testFlag (Qt::ControlModifier);
// auto alt = modifiers.testFlag (Qt::AltModifier);
// basic mode sanity checks
auto const& parts = message.string ().split (' ', QString::SkipEmptyParts);
auto const& parts = message.string ().split (' ', SkipEmptyParts);
if (parts.size () < 5) return;
auto const& mode = parts.at (4).left (1);
if (("JT9+JT65" == m_mode && !("@" == mode || "#" == mode))
@ -4530,7 +4569,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
ui->dxCallEntry->setText(hiscall);
}
QStringList w=message.string().mid(22).remove("<").remove(">").split(" ",QString::SkipEmptyParts);
QStringList w=message.string().mid(22).remove("<").remove(">").split(" ",SkipEmptyParts);
int nw=w.size();
if(nw>=4) {
if(message_words.size()<3) return;
@ -4622,7 +4661,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
MessageBox::information_message (this, msg);
}
QStringList t=message.string().split(' ', QString::SkipEmptyParts);
QStringList t=message.string().split(' ', SkipEmptyParts);
int n=t.size();
QString t0=t.at(n-2);
QString t1=t0.right(1);
@ -4916,7 +4955,7 @@ void MainWindow::processMessage (DecodedText const& message, Qt::KeyboardModifie
if (hisgrid.contains (grid_regexp)) {
if(ui->dxGridEntry->text().mid(0,4) != hisgrid) ui->dxGridEntry->setText(hisgrid);
}
lookup(false);
lookup();
m_hisGrid = ui->dxGridEntry->text();
QString rpt = message.report();
@ -5324,7 +5363,7 @@ void MainWindow::clearDX ()
m_QSOProgress = CALLING;
}
void MainWindow::lookup(bool lookupButtonClicked)
void MainWindow::lookup()
{
QString hisCall {ui->dxCallEntry->text()};
QString hisgrid0 {ui->dxGridEntry->text()};
@ -5337,10 +5376,6 @@ void MainWindow::lookup(bool lookupButtonClicked)
for(int i=0; i<999999; i++) {
n=f.readLine(c,sizeof(c));
if(n <= 0) {
if(lookupButtonClicked) {
QString msg=hisCall + tr(" not found in CALL3.TXT");
MessageBox::information_message (this, msg);
}
if(!hisgrid0.contains(grid_regexp)) {
ui->dxGridEntry->clear();
}
@ -5368,7 +5403,7 @@ void MainWindow::lookup(bool lookupButtonClicked)
void MainWindow::on_lookupButton_clicked() //Lookup button
{
lookup(true);
lookup();
}
void MainWindow::on_addButton_clicked() //Add button
@ -5400,7 +5435,13 @@ void MainWindow::on_addButton_clicked() //Add button
}
if(f1.size()==0) {
QTextStream out(&f1);
out << "ZZZZZZ" << endl;
out << "ZZZZZZ"
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
f1.close();
f1.open(QIODevice::ReadOnly | QIODevice::Text);
}
@ -5547,6 +5588,7 @@ void MainWindow::on_tx6_editingFinished() //tx6 edited
void MainWindow::on_dxCallEntry_textChanged (QString const& call)
{
m_hisCall = call;
ui->dxGridEntry->clear();
statusChanged();
statusUpdate ();
}
@ -6978,7 +7020,13 @@ void MainWindow::handle_transceiver_update (Transceiver::TransceiverState const&
QTextStream out(&f2);
out << QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd hh:mm")
<< " " << qSetRealNumberPrecision (12) << (m_freqNominal / 1.e6) << " MHz "
<< m_mode << endl;
<< m_mode
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
f2.close();
} else {
MessageBox::warning_message (this, tr ("File Error")
@ -7556,7 +7604,7 @@ void MainWindow::replayDecodes ()
// appended info
if (message.size() >= 4 && message.left (4) != "----")
{
auto const& parts = message.split (' ', QString::SkipEmptyParts);
auto const& parts = message.split (' ', SkipEmptyParts);
if (parts.size () >= 5 && parts[3].contains ('.')) // WSPR
{
postWSPRDecode (false, parts);
@ -7574,7 +7622,7 @@ void MainWindow::replayDecodes ()
void MainWindow::postDecode (bool is_new, QString const& message)
{
auto const& decode = message.trimmed ();
auto const& parts = decode.left (22).split (' ', QString::SkipEmptyParts);
auto const& parts = decode.left (22).split (' ', SkipEmptyParts);
if (parts.size () >= 5)
{
auto has_seconds = parts[0].size () > 4;
@ -7647,9 +7695,11 @@ void MainWindow::p1ReadFromStdout() //p1readFromStdout
ui->DecodeButton->setChecked (false);
if(m_uploadSpots
&& m_config.is_transceiver_online ()) { // need working rig control
float x=qrand()/((double)RAND_MAX + 1.0);
int msdelay=20000*x;
uploadTimer.start(msdelay); //Upload delay
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
uploadTimer.start(QRandomGenerator::global ()->bounded (0, 20000)); // Upload delay
#else
uploadTimer.start(20000 * qrand()/((double)RAND_MAX + 1.0)); // Upload delay
#endif
} else {
QFile f(QDir::toNativeSeparators(m_config.writeable_data_dir ().absolutePath()) + "/wspr_spots.txt");
if(f.exists()) f.remove();
@ -7749,7 +7799,13 @@ void MainWindow::WSPR_history(Frequency dialFreq, int ndecodes)
QFile f {m_config.writeable_data_dir ().absoluteFilePath ("WSPR_history.txt")};
if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
QTextStream out(&f);
out << t1 << endl;
out << t1
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
f.close();
} else {
MessageBox::warning_message (this, tr ("File Error")
@ -7839,18 +7895,22 @@ void MainWindow::WSPR_scheduling ()
if (hop_data.frequencies_index_ >= 0) { // new band
ui->bandComboBox->setCurrentIndex (hop_data.frequencies_index_);
on_bandComboBox_activated (hop_data.frequencies_index_);
m_cmnd.clear ();
QStringList prefixes {".bat", ".cmd", ".exe", ""};
QString target;
for (auto const& prefix : prefixes)
{
auto const& path = m_appDir + "/user_hardware" + prefix;
QFile f {path};
if (f.exists ()) {
m_cmnd = QDir::toNativeSeparators (f.fileName ()) + ' ' +
m_config.bands ()->find (m_freqNominal).remove ('m');
target = QDir {m_appDir}.absoluteFilePath (QLatin1String {"user_hardware"});
QFileInfo f {target + prefix};
if (f.isExecutable ()) {
break;
}
}
if(m_cmnd!="") p3.start(m_cmnd); // Execute user's hardware controller
if (target.size ())
{
// Execute user's hardware controller
p3.start(QDir::toNativeSeparators (target)
, QStringList {m_config.bands ()->find (m_freqNominal).remove ('m')});
}
// Produce a short tuneup signal
m_tuneup = false;
@ -8176,7 +8236,13 @@ void MainWindow::write_transmit_entry (QString const& file_name)
out << time.toString("yyMMdd_hhmmss")
<< " Transmitting " << qSetRealNumberPrecision (12) << (m_freqNominal / 1.e6)
<< " MHz " << m_modeTx
<< ": " << m_currentMessage << endl;
<< ": " << m_currentMessage
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
f.close();
}
else
@ -8264,7 +8330,7 @@ QString MainWindow::sortHoundCalls(QString t, int isort, int max_dB)
QString msg,houndCall,t1;
QString ABC{"ABCDEFGHIJKLMNOPQRSTUVWXYZ _"};
QList<int> list;
int i,j,k,m,n,nlines;
int i,j,k,n,nlines;
bool bReverse=(isort >= 3);
isort=qAbs(isort);
@ -8281,20 +8347,20 @@ QString MainWindow::sortHoundCalls(QString t, int isort, int max_dB)
j=0;
t="";
for(auto a: map.keys()) {
t1=map[a].split(" ",QString::SkipEmptyParts).at(2);
t1=map[a].split(" ",SkipEmptyParts).at(2);
int nsnr=t1.toInt(); // get snr
if(nsnr <= max_dB) { // keep only if snr in specified range
if(isort==1) t += map[a] + "\n";
if(isort==3 or isort==4) {
i=2; // sort Hound calls by snr
if(isort==4) i=4; // sort Hound calls by distance
t1=map[a].split(" ",QString::SkipEmptyParts).at(i);
t1=map[a].split(" ",SkipEmptyParts).at(i);
n=1000*(t1.toInt()+100) + j; // pack (snr or dist) and index j into n
list.insert(j,n); // add n to list at [j]
}
if(isort==2) { // sort Hound calls by grid
t1=map[a].split(" ",QString::SkipEmptyParts).at(1);
t1=map[a].split(" ",SkipEmptyParts).at(1);
if(t1=="....") t1="ZZ99";
int i1=ABC.indexOf(t1.mid(0,1));
int i2=ABC.indexOf(t1.mid(1,1));
@ -8331,11 +8397,13 @@ QString MainWindow::sortHoundCalls(QString t, int isort, int max_dB)
a[i]=i;
}
for(i=nn-1; i>-1; i--) {
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
j = (i + 1) * QRandomGenerator::global ()->generateDouble ();
#else
j=(i+1)*double(qrand())/RAND_MAX;
m=a[j];
a[j]=a[i];
a[i]=m;
t += lines2.at(m) + "\n";
#endif
std::swap (a[j], a[i]);
t += lines2.at(a[i]) + "\n";
}
}
@ -8359,13 +8427,13 @@ void MainWindow::selectHound(QString line)
*/
if(line.length()==0) return;
QString houndCall=line.split(" ",QString::SkipEmptyParts).at(0);
QString houndCall=line.split(" ",SkipEmptyParts).at(0);
// Don't add a call already enqueued or in QSO
if(ui->textBrowser4->toPlainText().indexOf(houndCall) >= 0) return;
QString houndGrid=line.split(" ",QString::SkipEmptyParts).at(1); // Hound caller's grid
QString rpt=line.split(" ",QString::SkipEmptyParts).at(2); // Hound SNR
QString houndGrid=line.split(" ",SkipEmptyParts).at(1); // Hound caller's grid
QString rpt=line.split(" ",SkipEmptyParts).at(2); // Hound SNR
m_houndCallers=m_houndCallers.remove(line+"\n"); // Remove t from sorted Hound list
m_nSortedHounds--;
@ -8729,9 +8797,20 @@ void MainWindow::writeFoxQSO(QString const& msg)
QFile f {m_config.writeable_data_dir ().absoluteFilePath ("FoxQSO.txt")};
if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
QTextStream out(&f);
out << QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd hh:mm:ss")
<< " " << fixed << qSetRealNumberPrecision (3) << (m_freqNominal/1.e6)
<< t << msg << endl;
out << QDateTime::currentDateTimeUtc().toString("yyyy-MM-dd hh:mm:ss") << " "
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::fixed
#else
<< fixed
#endif
<< qSetRealNumberPrecision (3) << (m_freqNominal/1.e6)
<< t << msg
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
f.close();
} else {
MessageBox::warning_message (this, tr("File Open Error"),
@ -8858,7 +8937,13 @@ void MainWindow::write_all(QString txRx, QString message)
QFile f{m_config.writeable_data_dir().absoluteFilePath(file_name)};
if (f.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append)) {
QTextStream out(&f);
out << line << endl;
out << line
#if QT_VERSION >= QT_VERSION_CHECK (5, 15, 0)
<< Qt::endl
#else
<< endl
#endif
;
f.close();
} else {
auto const& message2 = tr ("Cannot open \"%1\" for append: %2")

View File

@ -3,6 +3,8 @@
#define MAINWINDOW_H
#include <QMainWindow>
#include <QString>
#include <QStringList>
#include <QLabel>
#include <QThread>
#include <QProcess>
@ -605,8 +607,7 @@ private:
QString m_rptRcvd;
QString m_qsoStart;
QString m_qsoStop;
QString m_cmnd;
QString m_cmndP1;
QStringList m_cmndP1;
QString m_msgSent0;
QString m_calls;
QString m_CQtype;
@ -700,7 +701,7 @@ private:
void genStdMsgs(QString rpt, bool unconditional = false);
void genCQMsg();
void clearDX ();
void lookup(bool lookupButtonClicked);
void lookup();
void ba2msg(QByteArray ba, char* message);
void msgtype(QString t, QLineEdit* tx);
void stub();
@ -713,7 +714,7 @@ private:
void pskPost(DecodedText const& decodedtext);
void displayDialFrequency ();
void transmitDisplay (bool);
void processMessage(DecodedText const&, Qt::KeyboardModifiers = 0);
void processMessage(DecodedText const&, Qt::KeyboardModifiers = Qt::NoModifier);
void replyToCQ (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text, bool low_confidence, quint8 modifiers);
void locationChange(QString const& location);
void replayDecodes ();