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: private:
Q_SLOT void start_recording () 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_); source_.start (output_);
if (!notify_interval_) QTimer::singleShot (duration_ * 1000, Qt::PreciseTimer, this, &Record::stop_recording); 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 () Q_SLOT void notify ()
{ {
auto length = source_.elapsedUSecs (); 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 (); if (length >= duration_ * 1000 * 1000) stop_recording ();
} }
@ -85,7 +103,13 @@ private:
auto length = source_.elapsedUSecs (); auto length = source_.elapsedUSecs ();
source_.stop (); source_.stop ();
qtout << QString {"%1 μs recorded "}.arg (length) << '(' << source_.format ().framesForBytes (output_->size ()) << " frames recorded)\n"; 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 (); Q_EMIT done ();
} }
@ -134,15 +158,33 @@ public:
private: private:
Q_SLOT void start_playback () 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_); 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 () Q_SLOT void notify ()
{ {
auto length = sink_.elapsedUSecs (); 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) Q_SLOT void sink_state_changed (QAudio::State state)
@ -175,7 +217,13 @@ private:
auto length = sink_.elapsedUSecs (); auto length = sink_.elapsedUSecs ();
sink_.stop (); sink_.stop ();
qtout << QString {"%1 μs rendered "}.arg (length) << '(' << sink_.format ().framesForBytes (input_->size ()) << " frames rendered)\n"; 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 (); Q_EMIT done ();
} }
@ -258,7 +306,13 @@ int main(int argc, char *argv[])
int n {0}; int n {0};
for (auto const& device : input_devices) 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; return 0;
} }
@ -269,7 +323,13 @@ int main(int argc, char *argv[])
int n {0}; int n {0};
for (auto const& device : output_devices) 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; return 0;
} }
@ -352,7 +412,13 @@ int main(int argc, char *argv[])
auto source = input_device ? input_devices[input_device - 1] : QAudioDeviceInfo::defaultInputDevice (); auto source = input_device ? input_devices[input_device - 1] : QAudioDeviceInfo::defaultInputDevice ();
if (!source.isFormatSupported (audio_format)) 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); audio_format = source.nearestFormat (audio_format);
} }
BWFFile output_file {audio_format, ofi.filePath ()}; BWFFile output_file {audio_format, ofi.filePath ()};

View File

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

View File

@ -887,7 +887,7 @@ message (STATUS "hamlib_LIBRARY_DIRS: ${hamlib_LIBRARY_DIRS}")
# #
# Widgets finds its own dependencies. # 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) if (WIN32)
add_definitions (-DQT_NEEDS_QTMAIN) add_definitions (-DQT_NEEDS_QTMAIN)
@ -1111,9 +1111,7 @@ set (LANGUAGES
) )
foreach (lang_ ${LANGUAGES}) foreach (lang_ ${LANGUAGES})
file (TO_NATIVE_PATH ${CMAKE_SOURCE_DIR}/translations/wsjtx_${lang_}.ts ts_) file (TO_NATIVE_PATH ${CMAKE_SOURCE_DIR}/translations/wsjtx_${lang_}.ts ts_)
if (EXISTS "${ts_}")
list (APPEND TS_FILES ${ts_}) list (APPEND TS_FILES ${ts_})
endif ()
set (qt_translations_ "${QT_TRANSLATIONS_DIR}/qtbase_${lang_}.qm") set (qt_translations_ "${QT_TRANSLATIONS_DIR}/qtbase_${lang_}.qm")
if (EXISTS "${qt_translations_}") if (EXISTS "${qt_translations_}")
add_custom_command ( add_custom_command (
@ -1378,9 +1376,9 @@ set_target_properties (wsjtx PROPERTIES
target_include_directories (wsjtx PRIVATE ${FFTW3_INCLUDE_DIRS}) target_include_directories (wsjtx PRIVATE ${FFTW3_INCLUDE_DIRS})
if (APPLE) 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 () 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) if (OpenMP_C_FLAGS)
set_target_properties (wsjtx PROPERTIES set_target_properties (wsjtx PROPERTIES
COMPILE_FLAGS "${OpenMP_C_FLAGS}" COMPILE_FLAGS "${OpenMP_C_FLAGS}"
@ -1396,7 +1394,6 @@ else ()
) )
endif () endif ()
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 # make a library for WSJT-X UDP servers
# add_library (wsjtx_udp SHARED ${UDP_library_CXXSRCS}) # add_library (wsjtx_udp SHARED ${UDP_library_CXXSRCS})
@ -1416,8 +1413,7 @@ set_target_properties (wsjtx_udp-static PROPERTIES
OUTPUT_NAME wsjtx_udp OUTPUT_NAME wsjtx_udp
) )
target_compile_definitions (wsjtx_udp-static PUBLIC UDP_STATIC_DEFINE) target_compile_definitions (wsjtx_udp-static PUBLIC UDP_STATIC_DEFINE)
#qt5_use_modules (wsjtx_udp Network) target_link_libraries (wsjtx_udp-static Qt5::Network Qt5::Gui)
qt5_use_modules (wsjtx_udp-static Network Gui)
generate_export_header (wsjtx_udp-static BASE_NAME udp) generate_export_header (wsjtx_udp-static BASE_NAME udp)
add_executable (udp_daemon UDPExamples/UDPDaemon.cpp UDPExamples/udp_daemon.rc ${WSJTX_ICON_FILE}) 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 |IL|IN|KS|KY|LA|LAX|MAR|MB|MDC
|ME|MI|MN|MO|MS|MT|NC|ND|NE|NFL |ME|MI|MN|MO|MS|MT|NC|ND|NE|NFL
|NH|NL|NLI|NM|NNJ|NNY|NT|NTX|NV |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 |PR|QC|RI|SB|SC|SCV|SD|SDG|SF
|SFL|SJV|SK|SNJ|STX|SV|TN|UT|VA |SFL|SJV|SK|SNJ|STX|SV|TN|UT|VA
|VI|VT|WCF|WI|WMA|WNY|WPA|WTX |VI|VT|WCF|WI|WMA|WNY|WPA|WTX

View File

@ -1,47 +1,28 @@
Notes on WSJT-X Installation for Mac OS X 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 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 you change the name in the Applications folder from WSJT-X to WSJT-X_previous
before proceeding. before proceeding.
If you have installed a previous version of WSJT-X before then there is no 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. 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: BEGIN:
There are some system matters you must deal with first. Open a Terminal window Double-click on the wsjtx-...-Darwin.dmg file you have downloaded from K1JT's web-site.
by going to Applications->Utilities and clicking on Terminal.
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 Along with this ReadMe file there is a file: sysctl.conf which must be copied to a
the code. The normal allocation of shared memory on a Mac is insufficient and this system area by typing this line in the Terminal window and then pressing the Return key.
has to be increased. You should use a Mac editor to examine sysctl.conf.
There are two important parameters that you need to consider. shmmax determines the sudo cp /Volumes/WSJT-X/sysctl.conf /etc
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 you will be asked for your normal password because authorisation is needed to copy this file.
"Section 14. Platform Dependencies" in the User Guide. The second important parameter (Your password will not be echoed but press the Return key when completed.)
shmall=17920 determines how many instances are permitted. This is calculated as: Now re-boot your Mac. This is necessary to install the changes. After the
(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
reboot you should re-open the Terminal window as before and you can check that the reboot you should re-open the Terminal window as before and you can check that the
change has been made by typing: change has been made by typing:
@ -50,10 +31,9 @@ change has been made by typing:
If shmmax is not shown as 14680064 then contact me since WSJT-X will fail to load with 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". an error message: "Unable to create shared memory segment".
You are now finished with system changes. You should make certain that NO error messages You can now close the Terminal window. It will not be necessary to repeat this procedure
have been produced during these steps. You can now close the Terminal window. It will again, even when you download an updated version of WSJT-X. It might be necessary if you
not be necessary to repeat this procedure again, even when you download an updated upgrade macOS.
version of WSJT-X.
NEXT: NEXT:
@ -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 I recommend checking the 4 boxes under the Display heading and the first 4 boxes under
the Behaviour heading. the Behaviour heading.
IMPORTANT: If you are using macOS 10.14 (Mojave) it is important to note that the default setting Depending on your macOS you might see a pop-up window suggesting that wsjtx wants to use the
for audio input is "block". In order to receive audio from WSJT-X you must visit microphone. What this means is that audio input must be allowed. Agree.
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.
Next visit the Audio panel and select the Audio Codec you use to communicate between 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 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. 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 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. at the end of the QSO. Visit Section 11 of the User Guide for information about log files
These are a simple wsjtx.log file and wsjtx_log.adi which is formatted for use with and how to access them.
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.
Finally, visit the Radio panel. WSJT-X is most effective when operated with CAT 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 control. You will need to install the relevant Mac device driver for your rig,
be located in the device driver directory /dev. You should install your driver and then re-launch WSJT-X. Return to the Radio panel in Preferences and in
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 you
the "Serial port" panel select your driver from the list that is presented. If do not know where to get an appropriate driver, contact me.
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.
WSJT-X needs the Mac clock to be accurate. Visit System Preferences > Date & Time 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. 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 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. Please email me if you have problems.
--- John G4KLA (g4kla@rmnjmn.co.uk) --- 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 <QStringList>
#include <QRegularExpression> #include <QRegularExpression>
#include <QDebug> #include <QDebug>
#include "qt_helpers.hpp"
extern "C" { extern "C" {
bool stdmsg_(char const * msg, fortran_charlen_t); bool stdmsg_(char const * msg, fortran_charlen_t);
@ -58,7 +59,7 @@ QStringList DecodedText::messageWords () const
return words_re.match(t).capturedTexts(); return words_re.match(t).capturedTexts();
} }
// simple word split for free text messages // 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 // add whole message as item 0 to mimic RE capture list
words.prepend (message_); words.prepend (message_);
return words; return words;
@ -122,7 +123,7 @@ bool DecodedText::report(QString const& myBaseCall, QString const& dxBaseCall, /
{ {
if (message_.size () < 1) return false; if (message_.size () < 1) return false;
QStringList const& w = message_.split(" ",QString::SkipEmptyParts); QStringList const& w = message_.split(" ", SkipEmptyParts);
if (w.size () if (w.size ()
&& is_standard_ && (w[0] == myBaseCall && is_standard_ && (w[0] == myBaseCall
|| w[0].endsWith ("/" + myBaseCall) || w[0].endsWith ("/" + myBaseCall)

View File

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

View File

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

26
NEWS
View File

@ -13,6 +13,32 @@
Copyright 2001 - 2020 by Joe Taylor, K1JT. 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 Release: WSJT-X 2.2.1
June 6, 2020 June 6, 2020
--------------------- ---------------------

View File

@ -69,11 +69,13 @@ public:
void download (QUrl url) void download (QUrl url)
{ {
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
if (QNetworkAccessManager::Accessible != network_manager_->networkAccessible ()) if (QNetworkAccessManager::Accessible != network_manager_->networkAccessible ())
{ {
// try and recover network access for QNAM // try and recover network access for QNAM
network_manager_->setNetworkAccessible (QNetworkAccessManager::Accessible); network_manager_->setNetworkAccessible (QNetworkAccessManager::Accessible);
} }
#endif
QNetworkRequest request {url}; QNetworkRequest request {url};
request.setRawHeader ("User-Agent", "WSJT LotW User Downloader"); 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} : QObject {self}
, m_ {id, version, revision, server_port, this} , 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) connect (&*m_, static_cast<void (impl::*) (impl::SocketError)> (&impl::error)
, [this] (impl::SocketError e) , [this] (impl::SocketError e)
{ {
@ -441,6 +442,11 @@ MessageClient::MessageClient (QString const& id, QString const& version, QString
Q_EMIT error (m_->errorString ()); Q_EMIT error (m_->errorString ());
} }
}); });
#else
connect (&*m_, &impl::errorOccurred, [this] (impl::SocketError) {
Q_EMIT error (m_->errorString ());
});
#endif
set_server (server); set_server (server);
} }

View File

@ -7,6 +7,9 @@
#include <QHostInfo> #include <QHostInfo>
#include <QTimer> #include <QTimer>
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
#include <QRandomGenerator>
#endif
#include "Network/MessageClient.hpp" #include "Network/MessageClient.hpp"
@ -43,7 +46,11 @@ PSK_Reporter::PSK_Reporter(MessageClient * message_client, QObject *parent) :
"00960004"; // Report time "00960004"; // Report time
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
m_randomId_h = QString("%1").arg(qrand(),8,16,QChar('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))); 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() void WSPRNet::work()
{ {
if (!urlQueue.isEmpty()) { if (!urlQueue.isEmpty()) {
#if QT_VERSION < QT_VERSION_CHECK (5, 15, 0)
if (QNetworkAccessManager::Accessible != networkManager->networkAccessible ()) { if (QNetworkAccessManager::Accessible != networkManager->networkAccessible ()) {
// try and recover network access for QNAM // try and recover network access for QNAM
networkManager->setNetworkAccessible (QNetworkAccessManager::Accessible); networkManager->setNetworkAccessible (QNetworkAccessManager::Accessible);
} }
#endif
QUrl url(urlQueue.dequeue()); QUrl url(urlQueue.dequeue());
QNetworkRequest request(url); QNetworkRequest request(url);
m_outstandingRequests << networkManager->get(request); m_outstandingRequests << networkManager->get(request);

View File

@ -13,6 +13,32 @@
Copyright 2001 - 2020 by Joe Taylor, K1JT. 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 Release: WSJT-X 2.2.1
June 6, 2020 June 6, 2020
--------------------- ---------------------

View File

@ -101,17 +101,17 @@ SampleDownloader::impl::impl (QSettings * settings
setWindowTitle (QApplication::applicationName () + " - " + tr ("Download Samples")); setWindowTitle (QApplication::applicationName () + " - " + tr ("Download Samples"));
button_box_.button (QDialogButtonBox::Close)->setDefault (true); button_box_.button (QDialogButtonBox::Close)->setDefault (true);
button_box_.addButton ("&Abort", QDialogButtonBox::DestructiveRole); button_box_.addButton (tr ("&Abort"), QDialogButtonBox::DestructiveRole);
button_box_.addButton ("&Refresh", QDialogButtonBox::ResetRole); button_box_.addButton (tr ("&Refresh"), QDialogButtonBox::ResetRole);
left_layout_.addWidget (&directory_); 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_button->setCheckable (true);
details_widget_.hide (); details_widget_.hide ();
details_layout_.setMargin (0); details_layout_.setMargin (0);
details_layout_.addRow ("Base URL for samples:", &url_line_edit_); details_layout_.addRow (tr ("Base URL for samples:"), &url_line_edit_);
details_layout_.addRow ("Only use HTTP:", &http_only_check_box_); details_layout_.addRow (tr ("Only use HTTP:"), &http_only_check_box_);
http_only_check_box_.setToolTip ("Check this is you get SSL/TLS errors"); http_only_check_box_.setToolTip (tr ("Check this is you get SSL/TLS errors"));
details_widget_.setLayout (&details_layout_); details_widget_.setLayout (&details_layout_);
main_layout_.addLayout (&left_layout_, 0, 0); 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)); file_icon_.addPixmap (style ()->standardPixmap (QStyle::SP_FileIcon));
setColumnCount (2); setColumnCount (2);
setHeaderLabels ({"File", "Progress"}); setHeaderLabels ({tr ("File"), tr ("Progress")});
header ()->setSectionResizeMode (QHeaderView::ResizeToContents); header ()->setSectionResizeMode (QHeaderView::ResizeToContents);
setItemDelegate (&item_delegate_); setItemDelegate (&item_delegate_);

View File

@ -121,10 +121,12 @@ bool RemoteFile::sync (QUrl const& url, bool local, bool force)
void RemoteFile::download (QUrl url) void RemoteFile::download (QUrl url)
{ {
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
if (QNetworkAccessManager::Accessible != network_manager_->networkAccessible ()) { if (QNetworkAccessManager::Accessible != network_manager_->networkAccessible ()) {
// try and recover network access for QNAM // try and recover network access for QNAM
network_manager_->setNetworkAccessible (QNetworkAccessManager::Accessible); network_manager_->setNetworkAccessible (QNetworkAccessManager::Accessible);
} }
#endif
if (url.isValid () && (!QSslSocket::supportsSsl () || http_only_)) 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"); Q_ASSERT_X (current_stream_, "TraceFile:message_handler", "no stream to write to");
{ {
QMutexLocker lock {&mutex_}; // thread safety - serialize writes to the trace file 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) if (QtFatalMsg == type)

View File

@ -10,6 +10,7 @@
#include <QDir> #include <QDir>
#include "Network/NetworkServerLookup.hpp" #include "Network/NetworkServerLookup.hpp"
#include "qt_helpers.hpp"
namespace namespace
{ {
@ -167,7 +168,7 @@ int HRDTransceiver::do_start ()
HRD_info << "Id: " << id << "\n"; HRD_info << "Id: " << id << "\n";
HRD_info << "Version: " << version << "\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 ()) if (radios.isEmpty ())
{ {
TRACE_CAT ("HRDTransceiver", "no rig found"); TRACE_CAT ("HRDTransceiver", "no rig found");
@ -178,7 +179,7 @@ int HRDTransceiver::do_start ()
Q_FOREACH (auto const& radio, radios) Q_FOREACH (auto const& radio, radios)
{ {
HRD_info << "\t" << radio << "\n"; 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])); 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"; HRD_info << "VFO count: " << vfo_count_ << "\n";
TRACE_CAT ("HRDTransceiver", "vfo count:" << vfo_count_); 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_); TRACE_CAT ("HRDTransceiver", "HRD Buttons: " << buttons_);
HRD_info << "Buttons: {" << buttons_.join (", ") << "}\n"; 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:"); TRACE_CAT ("HRDTransceiver", "Dropdowns:");
HRD_info << "Dropdowns:\n"; HRD_info << "Dropdowns:\n";
Q_FOREACH (auto const& dd, dropdown_names_) Q_FOREACH (auto const& dd, dropdown_names_)
@ -217,12 +218,12 @@ int HRDTransceiver::do_start ()
dropdowns_[dd] = selections; 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:-"); TRACE_CAT ("HRDTransceiver", "Sliders:-");
HRD_info << "Sliders:\n"; HRD_info << "Sliders:\n";
Q_FOREACH (auto const& s, slider_names_) 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 (", ") << "}"); TRACE_CAT ("HRDTransceiver", "\t" << s << ": {" << range.join (", ") << "}");
HRD_info << "\t" << s << ": {" << range.join (", ") << "}\n"; HRD_info << "\t" << s << ": {" << range.join (", ") << "}\n";
sliders_[s] = range; sliders_[s] = range;
@ -601,7 +602,7 @@ void HRDTransceiver::do_frequency (Frequency f, MODE m, bool /*no_ignore*/)
auto fo_string = QString::number (f); auto fo_string = QString::number (f);
if (vfo_count_ > 1 && reversed_) 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); send_simple_command ("set frequencies-hz " + QString::number (frequencies[0].toUInt ()) + ' ' + fo_string);
} }
else else
@ -687,14 +688,14 @@ void HRDTransceiver::do_tx_frequency (Frequency tx, MODE mode, bool /*no_ignore*
{ {
Q_ASSERT (vfo_count_ > 1); 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 ())); send_simple_command ("set frequencies-hz " + fo_string + ' ' + QString::number (frequencies[1].toUInt ()));
} }
else else
{ {
if (vfo_count_ > 1) 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); 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) 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) 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_rx_frequency (frequencies[reversed_ ? 1 : 0].toUInt ());
update_other_frequency (frequencies[reversed_ ? 0 : 1].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); 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; QString key;
if (RIG_MODEL_DUMMY == caps->rig_model) if (RIG_MODEL_DUMMY == caps->rig_model)
{ {
@ -185,6 +195,7 @@ HamlibTransceiver::HamlibTransceiver (TransceiverFactory::PTTMethod ptt_type, QS
QObject * parent) QObject * parent)
: PollingTransceiver {0, parent} : PollingTransceiver {0, parent}
, rig_ {rig_init (RIG_MODEL_DUMMY)} , rig_ {rig_init (RIG_MODEL_DUMMY)}
, ptt_only_ {true}
, back_ptt_port_ {false} , back_ptt_port_ {false}
, one_VFO_ {false} , one_VFO_ {false}
, is_dummy_ {true} , is_dummy_ {true}
@ -238,6 +249,7 @@ HamlibTransceiver::HamlibTransceiver (int model_number, TransceiverFactory::Para
QObject * parent) QObject * parent)
: PollingTransceiver {params.poll_interval, parent} : PollingTransceiver {params.poll_interval, parent}
, rig_ {rig_init (model_number)} , rig_ {rig_init (model_number)}
, ptt_only_ {false}
, back_ptt_port_ {TransceiverFactory::TX_audio_source_rear == params.audio_source} , back_ptt_port_ {TransceiverFactory::TX_audio_source_rear == params.audio_source}
, one_VFO_ {false} , one_VFO_ {false}
, is_dummy_ {RIG_MODEL_DUMMY == model_number} , is_dummy_ {RIG_MODEL_DUMMY == model_number}
@ -581,7 +593,7 @@ int HamlibTransceiver::do_start ()
tickle_hamlib_ = true; tickle_hamlib_ = true;
if (is_dummy_ && dummy_frequency_) if (is_dummy_ && !ptt_only_ && dummy_frequency_)
{ {
// return to where last dummy instance was // return to where last dummy instance was
// TODO: this is going to break down if multiple dummy rigs are used // 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 () void HamlibTransceiver::do_stop ()
{ {
if (is_dummy_) if (is_dummy_ && !ptt_only_)
{ {
rig_get_freq (rig_.data (), RIG_VFO_CURR, &dummy_frequency_); rig_get_freq (rig_.data (), RIG_VFO_CURR, &dummy_frequency_);
dummy_frequency_ = std::round (dummy_frequency_); dummy_frequency_ = std::round (dummy_frequency_);

View File

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

View File

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

View File

@ -39,11 +39,18 @@ public:
Radio::register_types (); Radio::register_types ();
connect (this, &QIODevice::readyRead, this, &MessageServer::impl::pending_datagrams); 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) connect (this, static_cast<void (impl::*) (SocketError)> (&impl::error)
, [this] (SocketError /* e */) , [this] (SocketError /* e */)
{ {
Q_EMIT self_->error (errorString ()); 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); connect (clock_, &QTimer::timeout, this, &impl::tick);
clock_->start (NetworkMessage::pulse * 1000); clock_->start (NetworkMessage::pulse * 1000);
} }

View File

@ -1,6 +1,6 @@
# Version number components # Version number components
set (WSJTX_VERSION_MAJOR 2) set (WSJTX_VERSION_MAJOR 2)
set (WSJTX_VERSION_MINOR 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_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 set (WSJTX_VERSION_IS_RELEASE 1) # set to 1 for final release build

View File

@ -242,7 +242,13 @@ namespace
QTextStream stream {&file}; QTextStream stream {&file};
Q_FOREACH (auto colour, colours_) 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 else

View File

@ -1,3 +1,5 @@
//status=edited
A text box entitled Astronomical Data provides information needed for A text box entitled Astronomical Data provides information needed for
tracking the sun or moon, compensating for EME Doppler shift, and tracking the sun or moon, compensating for EME Doppler shift, and
estimating EME Doppler spread and path degradation. Toggle the 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"] 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 and *El*, azimuth and elevation of the moon at your own location, in
degrees; *SelfDop*, *Width*, and *Delay*, the Doppler shift, full degrees; *SelfDop*, *Width*, and *Delay*, the Doppler shift, full
limb-to-limb Doppler spread in Hz, and delay of your own EME echoes in 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. part of the sky.
On the higher microwave bands, where Faraday rotation is minimal and On the higher microwave bands, where Faraday rotation is minimal and
linear polarization is often used, spatial offset will reduce signal linear polarization is often used, spatial offset reduces signal
levels. Some stations have implemented mechanical polarisation levels. Some stations have implemented mechanical polarisation
adjustment to overcome this loss, and the amount of rotation needed is adjustment to overcome this loss. The amount of rotation needed is
predicted in real time by the value of *Dpol*. Positive Dpol means predicted in real time by the value of *Dpol*. Positive Dpol means
that the antenna should be rotated in a clockwise direction looking that the antenna should be rotated in a clockwise direction looking
from behind the antenna towards the moon. For a dish antenna, the from behind the antenna towards the moon. For a dish antenna, the
feed should similarly be rotated clockwise looking into the mouth of 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 the sun, moon, and planets at a specified time is embodied in a
numerical model of the solar system maintained at the Jet Propulsion numerical model of the solar system maintained at the Jet Propulsion
Laboratory. The model has been numerically integrated to produce 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 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 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 //.Misc Controls Center
image::misc-controls-center.png[align="center",alt="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, starting at 0. Uncheck this box to transmit in the odd
sequences. The correct selection is made automatically when you sequences. The correct selection is made automatically when you
double-click on a decoded text line, as described in the double-click on a decoded text line, as described in the
<<TUTORIAL,Basic Operating Tutorial>>. <<TUTORIAL,Basic Operating Tutorial>>.
* The Tx and Rx audio frequencies can be set automatically by * 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. can also be adjusted using the spinner controls.
* You can copy values between the *Tx Freq* and *Rx Freq* boxes by * You can force Tx frequency to the current Rx frequency by clicking
clicking on the up/down arrows between the controls. Your the *Tx<-Rx* button, and vice-versa for *Rx<-Tx*. The on-the-air
on-the-air frequency is the sum of dial frequency and audio Tx frequency of your lowest JT9 or JT65 tone is the sum of dial frequency
frequency. By convention we define the frequency of WSJT-X modes as and audio Tx frequency.
the frequency of the lowest tone.
* Check the box *Hold Tx Freq* to ensure that the specified Tx * Check the box *Hold Tx Freq* to ensure that the specified Tx
frequency is not changed automatically when you double-click on frequency is not changed automatically when you double-click on
decoded text or a signal in the waterfall. decoded text or a signal in the waterfall.
* For modes lacking a multi-decode feature, or when *Enable * 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.
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.
* The *Report* control lets you change a signal report that has been * The *Report* control lets you change an automatically inserted signal report. Typical reports for the various modes fall in
inserted automatically. Typical reports for the various modes fall in
the range 30 to +20 dB. Remember that JT65 reports saturate at an the range 30 to +20 dB. Remember that JT65 reports saturate at an
upper limit of -1 dB. upper limit of -1 dB.
+ +
TIP: Consider reducing power if your QSO partner reports your 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!
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 * In some circumstances, especially on VHF and higher bands, you can
select a supported submode of the active mode by using the *Submode* 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 * Spinner control *T/R xx s* sets sequence lengths for transmission
and reception in ISCAT, MSK144, and the fast JT9 modes. 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 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 *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 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 in the range 010 to 999. Your CQ
message *Tx6* will then be transmitted at the calling frequency message *Tx6* will then be transmitted at the calling frequency
selected in the *Tx CQ nnn* spinner control. All other messages will 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 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: main window:
//.Misc Controls Left //.Misc Controls Left
image::misc-main-ui.png[align="center",alt="Misc Menu Items"] image::misc-main-ui.png[align="center",alt="Misc Menu Items"]
* A drop-down list of frequencies and bands at upper left lets you * A drop-down list of frequencies and bands in the upper, left-hand corner lets you
select the operating band and sets dial frequency to a value taken select the operating band. It also sets dial frequency to a value taken from the *Frequencies* tab on the *Settings* window. If CAT control
from the *Frequencies* tab on the *Settings* window. If CAT control is active, the radio's dial frequency is set accordingly; if not,
is active the radio's dial frequency will be set accordingly; if not,
you must tune the radio manually. you must tune the radio manually.
* Alternatively, you can enter a frequency (in MHz) or band name in * 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 // Status=edited
text windows on the main screen. Some controls appear only in certain
operating modes. The following controls appear just under the decoded text windows on
the main screen:
//.Main UI //.Main UI
image::main-ui-controls.png[align="center",width=650,alt="Main UI Controls"] 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 * When *CQ only* is checked, only messages from stations calling CQ are displayed in the left text panel.
be displayed in the left text panel.
* *Log QSO* raises a dialog window pre-filled with known information * *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 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 information before clicking *OK* to log the QSO. If you check *Prompt
me to log QSO* on the *Settings -> Reporting* tab, the program will 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
raise 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 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 sequence lengths, respectively. (Note that the actual start time may
have been earlier if repeats of early transmissions were required.) 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 //.Log QSO Window
image::log-qso.png[align="center",alt="Log QSO"] 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 freeze the waterfall or open and explore a previously recorded audio
file. file.
* *Monitor* toggles normal receive operation on or off. This button * *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 using CAT control, toggling *Monitor* OFF relinquishes control of the
rig; if *Monitor returns to last used frequency* is selected on 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. the original frequency.
* *Erase* clears the right-hand decoded text window. * *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 This process is useful for adjusting an antenna tuner or tuning an
amplifier. The button is highlighted in red while *Tune* is active. amplifier. The button is highlighted in red while *Tune* is active.
Toggle the button a second time or click *Halt Tx* to terminate the Toggle the button a second time or click *Halt Tx* to terminate the
*Tune* process. Note that activating *Tune* interrupts a receive *Tune* process.
sequence and will prevent decoding during that sequence.
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, * Uncheck the box *Menus* to make the top-of-window menus disappear,
leaving more vertical space for decoded messages. 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 Menus at top of the main window offer many options for configuration
and operation. Most of the items are self-explanatory; a few 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"] image::MacAppMenu.png[align="left",alt="Mac App Menu"]
This menu appears on the Macintosh only. *Settings* appears here, This menu appears on the Macintosh only. *Settings* appears here,
labeled as *Preferences*, rather than on the *File* menu. *About labeled as *Preferences*, rather than on the *File* menu. *About WSJT-X* appears here rather than on the *Help* menu.
WSJT-X* appears here rather than on the *Help* menu.
[[FILE_MENU]] [[FILE_MENU]]
==== File menu ==== File menu
@ -20,20 +19,12 @@ image::file-menu.png[align="left",alt="File Menu"]
==== Configuration Menu ==== Configuration Menu
image::config-menu.png[align="left",alt="File Menu"] image::config-menu.png[align="left",alt="File Menu"]
Most users of more than one mode prefer to create and use entries on Many users prefer to create and use entries on the *Configurations*
the *Configurations* menu for switching between modes. You can menu for switching between modes. Simply *Clone* the *Default* entry,
*Clone* the configuration currently in use, *Rename* the clone as *Rename* it as desired, and then make all desired settings for that
desired, and then make all desired settings for the new configuration. configuration. These settings are restored whenever you select that 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.
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 can also start the application from the command line in any desired
configuration. Use the command-line option configuration. Use the command-line option
`--config <configuration-name>`, or `-c` for short, as in these `--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 Two arrangements of controls are provided for generating and selecting
Tx messages. Controls familiar to users of program _WSJT_ 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"] image::traditional-msg-box.png[align="center",alt="Traditional Message Menu"]
* Select the next message to be transmitted (at the start of your next * 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 * To change to a specified Tx message immediately during a
transmission, click on a rectangular button under the *Now* label. transmission, click a rectangular button in the *Now* column.
Changing a Tx message in mid-stream will slightly reduce the chance of 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 correct decode, but it is usually OK if done in the first 10-20% of a transmission.
a transmission.
* All six Tx message fields are editable. You can modify an * All six Tx message fields are editable. You can modify an
automatically generated message or enter a desired message, keeping in automatically generated message or enter a desired message, keeping in
mind the limits on message content. See <<PROTOCOLS,Protocol mind the limits on message content. See <<PROTOCOLS,Protocol
Specifications>> for details. Specifications>> for details.
* Click on the pull-down arrow for message #5 to select one of the * Click the pull-down arrow for message #5 to select one of the
pre-stored messages entered on the *Settings | Tx Macros* tab. stored messages entered on the *Files -> Settings -> Tx Macros* tab.
Pressing *Enter* on a modified message #5 automatically adds that Pressing *Enter* on a modified message #5 automatically adds that
message to the stored macros. message to the stored macros.
* In some circumstances it may be desirable to make your QSOs as * In some circumstances it may be desirable to make your QSOs as
short as possible. To configure the program to start contacts with short as possible. To configure the program to start contacts with
message #2, disable message #1 by double-clicking on its round 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
radio-button or rectangular *Tx 1* button. Similarly, to send RR73 rather than RRR for message #4, double-click one of its buttons.
rather than RRR for message #4, double-click on one of its buttons.
The second arrangement of controls for generating and selecting The second arrangement of controls for generating and selecting
Tx messages appears on *Tab 2* of the Message Control Panel: 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 * You can enter and transmit anything (up to 13 characters, including
spaces) in the *Free Msg* box. spaces) in the *Free Msg* box.
* Click on the pull-down arrow in the *Free Msg* box to select a * Click the pull-down arrow in the *Free Msg* box to select a
pre-stored macro. Pressing *Enter* on a modified message here stored macro. Pressing *Enter* on a modified message here
automatically adds that message to the table of stored macros. automatically adds that message to the table of stored macros.
+ +
TIP: During a transmission the actual message being sent always 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). screen).

View File

@ -1,17 +1,16 @@
// Status=review // Status=edited
Download and execute the package file {win32} (Win 7, Win 8, Win10, Download and execute the package file {win32} (WinXP, Vista, Win 7,
32-bit) or {win64} (Win 7, Win 8, Win10, 64-bit) following these Win 8, Win10, 32-bit) or {win64} (Vista, Win 7, Win 8, Win10, 64-bit)
instructions: following these instructions:
* Install _WSJT-X_ into its own directory, for example `C:\WSJTX` or ` * Install _WSJT-X_ into its own directory, for example `C:\WSJTX` or `C:\WSJT\WSJTX`, rather than the conventional location `C:\Program
C:\WSJT\WSJTX`, rather than the conventional location `C:\Program
Files ...\WSJTX`. 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. 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 + directory +
`C:\Users\<username>\AppData\Local\WSJT-X`. `C:\Users\<username>\AppData\Local\WSJT-X`.
@ -30,27 +29,23 @@ TIP: Your computer may be configured so that this directory is
[[OPENSSL]] [[OPENSSL]]
* _WSJT-X_ requires the _OpenSSL_ libraries to be installed, and image:LoTW_TLS_error.png[_WSJT-X_ LoTW download TLS error,
suitable libraries may already be installed on your system. If they align="center"]
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[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.
** You can download a suitable _OpenSSL_ package for Windows from
* You can download a suitable _OpenSSL_ package from {win_openssl_packages}; you need the latest *Windows Light*
{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. For the 32-bit _WSJT-X_ build use the latest Win32 v1.1.x
version of the _OpenSSL_ libraries, for the 64-bit _WSJT-X_ use the 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 latest Win64 v1.1.1 version of the _OpenSSL_ libraries (Note: it is
time of writing were {win32_openssl} and {win64_openssl}. It is OK OK to install both versions on a 64-bit system) which, at the time
to install both versions on a 64-bit system. of writing, were {win32_openssl} and {win64_openssl} respectively.
** Install the package and accept the default options, including the ** Install the package and accept the default options, including the
option to copy the _OpenSSL_ DLLs to the Windows system option to copy the _OpenSSL_ DLLs to the Windows system
directory. There is no obligation to donate to the _OpenSSL_ 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 NOTE: If you still get the same network error after installing the
_OpenSSL_ libraries then you also need to install 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 TIP: If you cannot install the _OpenSSL_ libraries or do not have an
Internet connection on the computer used to run 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 the _LoTW_ file manually. Go to
https://lotw.arrl.org/lotw-user-activity.csv in a web browser, https://lotw.arrl.org/lotw-user-activity.csv in a web browser,
download the file, then move it to the _WSJT-X_ log files download the file, then move it to the _WSJT-X_ log files
directory. This directory can be opened by selecting 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. * _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 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 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 *Advanced*, and select *16 bit, 48000 Hz (DVD Quality)*. Switch off
all audio enhancement features for these devices. all audio enhancement features for these devices.
* You can uninstall _WSJT-X_ by clicking its *Uninstall* link in the * You can uninstall _WSJT-X_ by clicking its *Uninstall* link in the
Windows *Start* menu, or by using *Uninstall a Program* on the Windows *Start* menu, or by using *Uninstall a Program* on the
Windows Control Panel Programs and Features option or in Settings *Windows Control Panel|Programs and Features* option or in *Settings|Apps* on Windows 10.
Apps and Features on Windows 10.

View File

@ -1,5 +1,9 @@
#include "getfile.h" #include "getfile.h"
#include <QDir> #include <QDir>
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
#include <QRandomGenerator>
#include <random>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <string.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 */ /* Generate gaussian random float with mean=0 and std_dev=1 */
float gran() 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; float fac,rsq,v1,v2;
static float gset; static float gset;
static int iset; static int iset;
@ -192,6 +200,7 @@ float gran()
gset = v1*fac; gset = v1*fac;
iset++; iset++;
return v2*fac; return v2*fac;
#endif
} }
int ptt(int nport, int ntx, int* iptt, int* nopen) 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; if(hInstLib == NULL) return 605;
// Get procedure addresses. // Get procedure addresses.
lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*)) lpfEnumProcesses = (BOOL(WINAPI *)(DWORD *,DWORD,DWORD*))(void (*)())
GetProcAddress( hInstLib, "EnumProcesses" ) ; GetProcAddress( hInstLib, "EnumProcesses" ) ;
lpfEnumProcessModules = (BOOL(WINAPI *)(HANDLE, HMODULE *, lpfEnumProcessModules = (BOOL(WINAPI *)(HANDLE, HMODULE *,
DWORD, LPDWORD)) GetProcAddress( hInstLib, "EnumProcessModules" ) ; DWORD, LPDWORD))(void (*)()) GetProcAddress( hInstLib, "EnumProcessModules" ) ;
lpfGetModuleBaseName =(DWORD (WINAPI *)(HANDLE, HMODULE, LPTSTR, lpfGetModuleBaseName =(DWORD (WINAPI *)(HANDLE, HMODULE, LPTSTR,
DWORD )) GetProcAddress( hInstLib, "GetModuleBaseNameA" ) ; DWORD ))(void (*)()) GetProcAddress( hInstLib, "GetModuleBaseNameA" ) ;
if(lpfEnumProcesses == NULL || lpfEnumProcessModules == NULL || if(lpfEnumProcesses == NULL || lpfEnumProcessModules == NULL ||
lpfGetModuleBaseName == NULL) { lpfGetModuleBaseName == NULL) {
@ -164,20 +164,20 @@ int killbyname(const char *szToTerminate)
// which does not have the Toolhelp32 // which does not have the Toolhelp32
// functions in the Kernel 32. // functions in the Kernel 32.
lpfCreateToolhelp32Snapshot= lpfCreateToolhelp32Snapshot=
(HANDLE(WINAPI *)(DWORD,DWORD)) (HANDLE(WINAPI *)(DWORD,DWORD))(void (*)())
GetProcAddress( hInstLib, GetProcAddress( hInstLib,
"CreateToolhelp32Snapshot" ) ; "CreateToolhelp32Snapshot" ) ;
lpfProcess32First= lpfProcess32First=
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32)) (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))(void (*)())
GetProcAddress( hInstLib, "Process32First" ) ; GetProcAddress( hInstLib, "Process32First" ) ;
lpfProcess32Next= lpfProcess32Next=
(BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32)) (BOOL(WINAPI *)(HANDLE,LPPROCESSENTRY32))(void (*)())
GetProcAddress( hInstLib, "Process32Next" ) ; GetProcAddress( hInstLib, "Process32Next" ) ;
lpfModule32First= lpfModule32First=
(BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32)) (BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))(void (*)())
GetProcAddress( hInstLib, "Module32First" ) ; GetProcAddress( hInstLib, "Module32First" ) ;
lpfModule32Next= lpfModule32Next=
(BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32)) (BOOL(WINAPI *)(HANDLE,LPMODULEENTRY32))(void (*)())
GetProcAddress( hInstLib, "Module32Next" ) ; GetProcAddress( hInstLib, "Module32Next" ) ;
if( lpfProcess32Next == NULL || if( lpfProcess32Next == NULL ||
lpfProcess32First == 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 ! the value of nrx is used to decide when mycall13 or dxcall13 should
! be used in place of a callsign from the hashtable ! 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 (NUSCAN=65) !Number of US states and Canadian provinces
parameter (MAXGRID4=32400) parameter (MAXGRID4=32400)
integer*8 n58 integer*8 n58
@ -228,7 +228,7 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
"ONS","OR ","ORG","PAC","PR ","QC ","RI ","SB ","SC ","SCV", & "ONS","OR ","ORG","PAC","PR ","QC ","RI ","SB ","SC ","SCV", &
"SD ","SDG","SF ","SFL","SJV","SK ","SNJ","STX","SV ","TN ", & "SD ","SDG","SF ","SFL","SJV","SK ","SNJ","STX","SV ","TN ", &
"UT ","VA ","VI ","VT ","WCF","WI ","WMA","WNY","WPA","WTX", & "UT ","VA ","VI ","VT ","WCF","WI ","WMA","WNY","WPA","WTX", &
"WV ","WWA","WY ","DX "/ "WV ","WWA","WY ","DX ","PE "/
data cmult/ & data cmult/ &
"AL ","AK ","AZ ","AR ","CA ","CO ","CT ","DE ","FL ","GA ", & "AL ","AK ","AZ ","AR ","CA ","CO ","CT ","DE ","FL ","GA ", &
"HI ","ID ","IL ","IN ","IA ","KS ","KY ","LA ","ME ","MD ", & "HI ","ID ","IL ","IN ","IA ","KS ","KY ","LA ","ME ","MD ", &
@ -303,6 +303,9 @@ subroutine unpack77(c77,nrx,msg,unpk77_success)
n10.eq.hashmy10) call_3='<'//trim(mycall13)//'>' n10.eq.hashmy10) call_3='<'//trim(mycall13)//'>'
msg=trim(call_1)//' RR73; '//trim(call_2)//' '//trim(call_3)//' '//crpt 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 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.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 ! 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) ! Check 0.3 and 0.4 (ARRL Field Day exchange)
! Example message: WA9XYZ KA1ABC R 16A EMA 28 28 1 4 3 7 71 ! 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*13 w(19)
character*77 c77 character*77 c77
character*6 bcall_1,bcall_2 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", & "ONS","OR ","ORG","PAC","PR ","QC ","RI ","SB ","SC ","SCV", &
"SD ","SDG","SF ","SFL","SJV","SK ","SNJ","STX","SV ","TN ", & "SD ","SDG","SF ","SFL","SJV","SK ","SNJ","STX","SV ","TN ", &
"UT ","VA ","VI ","VT ","WCF","WI ","WMA","WNY","WPA","WTX", & "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 if(nwords.lt.4 .or. nwords.gt.5) return
call chkcall(w(1),bcall_1,ok1) 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 max_iterations=30
nharderrors=-1 nharderrors=-1
nbadcrc=1 ! this is used upstream to flag good decodes.
fs2=12000.0/NDOWN fs2=12000.0/NDOWN
dt2=1.0/fs2 dt2=1.0/fs2
twopi=8.0*atan(1.0) twopi=8.0*atan(1.0)
@ -403,14 +402,12 @@ subroutine ft8b(dd0,newdat,nQSOProgress,nfqso,nftx,ndepth,nzhsym,lapon, &
dmin=0.0 dmin=0.0
norder=2 norder=2
maxosd=2 maxosd=2
if(ndepth.lt.3) maxosd=1 if(ndepth.eq.1) maxosd=-1 ! BP only
if(abs(nfqso-f1).le.napwid .or. abs(nftx-f1).le.napwid .or. ncontest.eq.7) then 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 maxosd=2
endif endif
if(nagain) then
norder=3
maxosd=1
endif
call timer('dec174_91 ',0) call timer('dec174_91 ',0)
Keff=91 Keff=91
call decode174_91(llrz,Keff,maxosd,norder,apmask,message91,cw, & 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) call timer('dec174_91 ',1)
msg37=' ' msg37=' '
nbadcrc=1
if(nharderrors.lt.0 .or. nharderrors.gt.36) cycle if(nharderrors.lt.0 .or. nharderrors.gt.36) cycle
if(count(cw.eq.0).eq.174) cycle !Reject the all-zero codeword if(count(cw.eq.0).eq.174) cycle !Reject the all-zero codeword
write(c77,'(77i1)') message77 write(c77,'(77i1)') message77
read(c77(72:74),'(b3)') n3 read(c77(72:74),'(b3)') n3
read(c77(75:77),'(b3)') i3 read(c77(75:77),'(b3)') i3
if(i3.gt.5 .or. (i3.eq.0.and.n3.gt.6)) cycle 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) call unpack77(c77,1,msg37,unpk77_success)
if(.not.unpk77_success) then if(.not.unpk77_success) cycle
cycle
endif
nbadcrc=0 ! If we get this far: valid codeword, valid (i3,n3), nonquirky message. nbadcrc=0 ! If we get this far: valid codeword, valid (i3,n3), nonquirky message.
call get_ft8_tones_from_77bits(message77,itone) call get_ft8_tones_from_77bits(message77,itone)
if(lsubtract) then 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 ! Calculate and insert the audio waveform
phi=0.0 phi=0.0
dphi = dphi + twopi*f0*dt !Shift frequency up by f0 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 if(icmplx .ne. 0) cwave=0. !Avoid writing to memory we may not have access to
call timer('gen_loop',0) call timer('gen_loop',0)

View File

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

View File

@ -442,9 +442,21 @@ bool WorkedBefore::add (QString const& call
QTextStream out {&file}; QTextStream out {&file};
if (!file.size ()) 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 () m_->worked_.emplace (call.toUpper (), grid.left (4).toUpper (), band.toUpper (), mode.toUpper ()
, entity.entity_name, entity.continent, entity.CQ_zone, entity.ITU_zone); , 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(operator_call!="") t+=" <operator:" + QString::number(operator_call.size()) + ">" + operator_call;
if (xSent.size ()) 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.size () > 1)
{ {
if (words.back ().toUInt ()) if (words.back ().toUInt ())
@ -126,7 +132,13 @@ QByteArray LogBook::QSOToADIF (QString const& hisCall, QString const& hisGrid, Q
} }
} }
if (xRcvd.size ()) { 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.size () == 2)
{ {
if (words.at (1).toUInt ()) if (words.at (1).toUInt ())

View File

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

View File

@ -4766,7 +4766,7 @@ Qt::Alignment QCPLayoutInset::insetAlignment(int index) const
else else
{ {
qDebug() << Q_FUNC_INFO << "Invalid element index:" << index; 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) 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(); return QDateTime(date).toTime_t();
# else #elif QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
return QDateTime(date).toMSecsSinceEpoch()/1000.0; return QDateTime(date).toMSecsSinceEpoch()/1000.0;
# endif #else
return date.startOfDay().toMSecsSinceEpoch()/1000.0;
#endif
} }
/* end of 'src/axis/axistickerdatetime.cpp' */ /* 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) void QCPAxisTickerText::addTicks(const QMap<double, QString> &ticks)
{ {
# if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
mTicks.unite(ticks); mTicks.unite(ticks);
#else
mTicks.insert(ticks);
#endif
} }
/*! \overload /*! \overload
@ -12598,9 +12604,11 @@ QCustomPlot::QCustomPlot(QWidget *parent) :
mBufferDevicePixelRatio(1.0), // will be adapted to primary screen below mBufferDevicePixelRatio(1.0), // will be adapted to primary screen below
mPlotLayout(0), mPlotLayout(0),
mAutoAddPlottableToLegend(true), mAutoAddPlottableToLegend(true),
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
mAntialiasedElements(QCP::aeNone), mAntialiasedElements(QCP::aeNone),
mNotAntialiasedElements(QCP::aeNone), mNotAntialiasedElements(QCP::aeNone),
mInteractions(0), mInteractions(0),
#endif
mSelectionTolerance(8), mSelectionTolerance(8),
mNoAntialiasingOnDrag(false), mNoAntialiasingOnDrag(false),
mBackgroundBrush(Qt::white, Qt::SolidPattern), mBackgroundBrush(Qt::white, Qt::SolidPattern),
@ -12617,7 +12625,9 @@ QCustomPlot::QCustomPlot(QWidget *parent) :
mReplotting(false), mReplotting(false),
mReplotQueued(false), mReplotQueued(false),
mOpenGlMultisamples(16), mOpenGlMultisamples(16),
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
mOpenGlAntialiasedElementsBackup(QCP::aeNone), mOpenGlAntialiasedElementsBackup(QCP::aeNone),
#endif
mOpenGlCacheLabelsBackup(true) mOpenGlCacheLabelsBackup(true)
{ {
setAttribute(Qt::WA_NoMousePropagation); setAttribute(Qt::WA_NoMousePropagation);
@ -14668,7 +14678,15 @@ void QCustomPlot::wheelEvent(QWheelEvent *event)
{ {
emit mouseWheel(event); emit mouseWheel(event);
// forward event to layerable under cursor: // 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) 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 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)) 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()); QRectF rectF(rect.normalized());
if (QCPAxisRect *affectedAxisRect = axisRectAt(rectF.topLeft())) if (QCPAxisRect *affectedAxisRect = axisRectAt(rectF.topLeft()))
{ {
@ -15013,7 +15031,7 @@ void QCustomPlot::processRectSelection(QRect rect, QMouseEvent *event)
{ {
QCPDataSelection dataSel = plottableInterface->selectTestRect(rectF, true); QCPDataSelection dataSel = plottableInterface->selectTestRect(rectF, true);
if (!dataSel.isEmpty()) 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: // only leave plottable with most selected points in map, since we will only select a single plottable:
if (!potentialSelections.isEmpty()) 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 while (it != potentialSelections.end()-1) // erase all except last element
it = potentialSelections.erase(it); 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: // 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()) while (it != potentialSelections.constBegin())
{ {
--it; --it;
@ -17619,14 +17637,24 @@ void QCPAxisRect::wheelEvent(QWheelEvent *event)
if (mRangeZoom != 0) if (mRangeZoom != 0)
{ {
double factor; double factor;
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
double wheelSteps = event->delta()/120.0; // a single step delta is +/-120 usually 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)) if (mRangeZoom.testFlag(Qt::Horizontal))
{ {
factor = qPow(mRangeZoomFactorHorz, wheelSteps); factor = qPow(mRangeZoomFactorHorz, wheelSteps);
for (int i=0; i<mRangeZoomHorzAxis.size(); ++i) for (int i=0; i<mRangeZoomHorzAxis.size(); ++i)
{ {
if (!mRangeZoomHorzAxis.at(i).isNull()) 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)) if (mRangeZoom.testFlag(Qt::Vertical))
@ -17635,7 +17663,13 @@ void QCPAxisRect::wheelEvent(QWheelEvent *event)
for (int i=0; i<mRangeZoomVertAxis.size(); ++i) for (int i=0; i<mRangeZoomVertAxis.size(); ++i)
{ {
if (!mRangeZoomVertAxis.at(i).isNull()) 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(); mParentPlot->replot();
@ -19262,7 +19296,7 @@ void QCPColorScale::setRangeDrag(bool enabled)
if (enabled) if (enabled)
mAxisRect.data()->setRangeDrag(QCPAxis::orientation(mType)); mAxisRect.data()->setRangeDrag(QCPAxis::orientation(mType));
else else
mAxisRect.data()->setRangeDrag(0); mAxisRect.data()->setRangeDrag(Qt::Orientations());
} }
/*! /*!
@ -19282,7 +19316,7 @@ void QCPColorScale::setRangeZoom(bool enabled)
if (enabled) if (enabled)
mAxisRect.data()->setRangeZoom(QCPAxis::orientation(mType)); mAxisRect.data()->setRangeZoom(QCPAxis::orientation(mType));
else 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))}; \ 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 inline
void throw_qstring (QString const& qs) 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> <message>
<location filename="../SampleDownloader/Directory.cpp" line="51"/> <location filename="../SampleDownloader/Directory.cpp" line="51"/>
<source>File</source> <source>File</source>
<translation></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../SampleDownloader/Directory.cpp" line="51"/> <location filename="../SampleDownloader/Directory.cpp" line="51"/>
<source>Progress</source> <source>Progress</source>
<translation></translation> <translation type="unfinished"></translation>
</message> </message>
<message> <message>
<location filename="../SampleDownloader/Directory.cpp" line="113"/> <location filename="../SampleDownloader/Directory.cpp" line="113"/>
@ -1079,10 +1079,6 @@ Error: %2 - %3</source>
<source>Freq (Hz)</source> <source>Freq (Hz)</source>
<translation>(Hz)</translation> <translation>(Hz)</translation>
</message> </message>
<message>
<source>Phase (Î )</source>
<translation type="vanished"> (Î )</translation>
</message>
<message> <message>
<location filename="../EqualizationToolsDialog.cpp" line="309"/> <location filename="../EqualizationToolsDialog.cpp" line="309"/>
<source>Phase (Π)</source> <source>Phase (Π)</source>
@ -2179,7 +2175,7 @@ Yellow when too low</source>
<message> <message>
<location filename="../widgets/mainwindow.ui" line="904"/> <location filename="../widgets/mainwindow.ui" line="904"/>
<source> Pwr</source> <source> Pwr</source>
<translation> </translation> <translation> </translation>
</message> </message>
<message> <message>
<location filename="../widgets/mainwindow.ui" line="914"/> <location filename="../widgets/mainwindow.ui" line="914"/>
@ -2258,6 +2254,11 @@ Yellow when too low</source>
<source>Set Tx frequency to Rx Frequency</source> <source>Set Tx frequency to Rx Frequency</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<location filename="../widgets/mainwindow.ui" line="1139"/>
<source></source>
<translation></translation>
</message>
<message> <message>
<location filename="../widgets/mainwindow.ui" line="1146"/> <location filename="../widgets/mainwindow.ui" line="1146"/>
<source>Frequency tolerance (Hz)</source> <source>Frequency tolerance (Hz)</source>
@ -2273,11 +2274,6 @@ Yellow when too low</source>
<source>Set Rx frequency to Tx Frequency</source> <source>Set Rx frequency to Tx Frequency</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<location filename="../widgets/mainwindow.ui" line="1139"/>
<source></source>
<translation></translation>
</message>
<message> <message>
<location filename="../widgets/mainwindow.ui" line="1189"/> <location filename="../widgets/mainwindow.ui" line="1189"/>
<source></source> <source></source>
@ -2414,7 +2410,7 @@ Not available to nonstandard callsign holders.</source>
<message> <message>
<location filename="../widgets/mainwindow.ui" line="1349"/> <location filename="../widgets/mainwindow.ui" line="1349"/>
<source>Rx All Freqs</source> <source>Rx All Freqs</source>
<translation type="unfinished"></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../widgets/mainwindow.ui" line="1358"/> <location filename="../widgets/mainwindow.ui" line="1358"/>
@ -2973,12 +2969,12 @@ ENTERを押してテキストを登録リストに追加.
<message> <message>
<location filename="../widgets/mainwindow.ui" line="2342"/> <location filename="../widgets/mainwindow.ui" line="2342"/>
<source>N List </source> <source>N List </source>
<translation>Nリスト </translation> <translation> </translation>
</message> </message>
<message> <message>
<location filename="../widgets/mainwindow.ui" line="2373"/> <location filename="../widgets/mainwindow.ui" line="2373"/>
<source>N Slots </source> <source>N Slots </source>
<translation>Nスロット </translation> <translation> </translation>
</message> </message>
<message> <message>
<location filename="../widgets/mainwindow.ui" line="2404"/> <location filename="../widgets/mainwindow.ui" line="2404"/>
@ -3004,8 +3000,8 @@ ENTERを押してテキストを登録リストに追加.
<message> <message>
<location filename="../widgets/mainwindow.ui" line="2452"/> <location filename="../widgets/mainwindow.ui" line="2452"/>
<source>More CQs</source> <source>More CQs</source>
<translatorcomment></translatorcomment> <translatorcomment>51CQを出す</translatorcomment>
<translation type="unfinished"></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../widgets/mainwindow.ui" line="2577"/> <location filename="../widgets/mainwindow.ui" line="2577"/>
@ -4030,7 +4026,7 @@ UDPサーバー %2:%3</translation>
<message> <message>
<location filename="../widgets/messageaveraging.ui" line="29"/> <location filename="../widgets/messageaveraging.ui" line="29"/>
<source> UTC Sync DT Freq </source> <source> UTC Sync DT Freq </source>
<translation type="unfinished"></translation> <translation></translation>
</message> </message>
</context> </context>
<context> <context>
@ -4172,6 +4168,7 @@ UDPサーバー %2:%3</translation>
<context> <context>
<name>QObject</name> <name>QObject</name>
<message> <message>
<location filename="../main.cpp" line="340"/>
<source>Invalid rig name - \ &amp; / not allowed</source> <source>Invalid rig name - \ &amp; / not allowed</source>
<translation type="vanished"> \ &amp; / 使</translation> <translation type="vanished"> \ &amp; / 使</translation>
</message> </message>
@ -4336,7 +4333,7 @@ Error(%2): %3</source>
<message> <message>
<location filename="../SampleDownloader.cpp" line="114"/> <location filename="../SampleDownloader.cpp" line="114"/>
<source>Check this is you get SSL/TLS errors</source> <source>Check this is you get SSL/TLS errors</source>
<translation type="unfinished"></translation> <translation>SSL/TLSエラーを表示</translation>
</message> </message>
<message> <message>
<location filename="../SampleDownloader.cpp" line="132"/> <location filename="../SampleDownloader.cpp" line="132"/>
@ -4615,7 +4612,7 @@ Error(%2): %3</source>
<location filename="../widgets/widegraph.ui" line="247"/> <location filename="../widgets/widegraph.ui" line="247"/>
<source>Ref Spec</source> <source>Ref Spec</source>
<translatorcomment></translatorcomment> <translatorcomment></translatorcomment>
<translation type="unfinished"></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../widgets/widegraph.ui" line="259"/> <location filename="../widgets/widegraph.ui" line="259"/>
@ -4899,7 +4896,7 @@ Error(%2): %3</source>
<message> <message>
<location filename="../Configuration.ui" line="301"/> <location filename="../Configuration.ui" line="301"/>
<source>Behavior</source> <source>Behavior</source>
<translation type="unfinished"></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../Configuration.ui" line="307"/> <location filename="../Configuration.ui" line="307"/>
@ -5328,7 +5325,7 @@ or bandwidth is selected).</source>
<message> <message>
<location filename="../Configuration.ui" line="1083"/> <location filename="../Configuration.ui" line="1083"/>
<source>If this is available then it is usually the correct mode for this program.</source> <source>If this is available then it is usually the correct mode for this program.</source>
<translation type="unfinished"></translation> <translation>使.</translation>
</message> </message>
<message> <message>
<location filename="../Configuration.ui" line="1086"/> <location filename="../Configuration.ui" line="1086"/>
@ -6214,92 +6211,114 @@ Right click for insert and delete options.</source>
<name>main</name> <name>main</name>
<message> <message>
<location filename="../main.cpp" line="83"/> <location filename="../main.cpp" line="83"/>
<location filename="../main.cpp" line="408"/> <location filename="../main.cpp" line="563"/>
<source>Fatal error</source> <source>Fatal error</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="88"/> <location filename="../main.cpp" line="88"/>
<location filename="../main.cpp" line="413"/> <location filename="../main.cpp" line="568"/>
<source>Unexpected fatal error</source> <source>Unexpected fatal error</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="194"/>
<source>Where &lt;rig-name&gt; is for multi-instance support.</source> <source>Where &lt;rig-name&gt; is for multi-instance support.</source>
<translation type="vanished">&lt;rig-name&gt;.</translation> <translation type="vanished">&lt;rig-name&gt;.</translation>
</message> </message>
<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> <source>Where &lt;configuration&gt; is an existing one.</source>
<translation type="vanished">&lt;configuration&gt;.</translation> <translation type="vanished">&lt;configuration&gt;.</translation>
</message> </message>
<message> <message>
<source>Where &lt;language&gt; is &lt;lang-code&gt;[-&lt;country-code&gt;].</source> <location filename="../main.cpp" line="201"/>
<translation type="vanished">&lt;language&gt;&lt;lang-code&gt;[-&lt;country-code&gt;].</translation> <source>configuration</source>
<translation></translation>
</message> </message>
<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> <source>Writable files in test location. Use with caution, for testing only.</source>
<translation type="vanished">. 使.</translation> <translation type="vanished">. 使.</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="216"/>
<source>Command line error</source> <source>Command line error</source>
<translation type="vanished"></translation> <translation type="vanished"></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="223"/>
<source>Command line help</source> <source>Command line help</source>
<translation type="vanished"></translation> <translation type="vanished"></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="228"/>
<source>Application version</source> <source>Application version</source>
<translation type="vanished"></translation> <translation type="vanished"></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="223"/> <location filename="../main.cpp" line="371"/>
<source>Another instance may be running</source> <source>Another instance may be running</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="224"/> <location filename="../main.cpp" line="372"/>
<source>try to remove stale lock file?</source> <source>try to remove stale lock file?</source>
<translation>?</translation> <translation>?</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="259"/> <location filename="../main.cpp" line="414"/>
<source>Failed to create a temporary directory</source> <source>Failed to create a temporary directory</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="260"/> <location filename="../main.cpp" line="415"/>
<location filename="../main.cpp" line="268"/> <location filename="../main.cpp" line="423"/>
<source>Path: &quot;%1&quot;</source> <source>Path: &quot;%1&quot;</source>
<translation>:&quot;%1&quot;</translation> <translation>:&quot;%1&quot;</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="266"/> <location filename="../main.cpp" line="421"/>
<source>Failed to create a usable temporary directory</source> <source>Failed to create a usable temporary directory</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="267"/> <location filename="../main.cpp" line="422"/>
<source>Another application may be locking the directory</source> <source>Another application may be locking the directory</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="300"/> <location filename="../main.cpp" line="455"/>
<source>Failed to create data directory</source> <source>Failed to create data directory</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="301"/> <location filename="../main.cpp" line="456"/>
<source>path: &quot;%1&quot;</source> <source>path: &quot;%1&quot;</source>
<translation>: &quot;%1&quot;</translation> <translation>: &quot;%1&quot;</translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="356"/> <location filename="../main.cpp" line="511"/>
<source>Shared memory error</source> <source>Shared memory error</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<location filename="../main.cpp" line="357"/> <location filename="../main.cpp" line="512"/>
<source>Unable to create shared memory segment</source> <source>Unable to create shared memory segment</source>
<translation></translation> <translation></translation>
</message> </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_1_line_edit->text() << '\n'
<< "ADDRESS: " << ui->addr_2_line_edit->text() << '\n'; << "ADDRESS: " << ui->addr_2_line_edit->text() << '\n';
if (log_) log_->export_qsos (out); 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; return;
} else { } else {
auto const& message = tr ("Cannot open \"%1\" for writing: %2") 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}; QTextStream out {&message};
out << " " << date << "\n" out << " " << date << "\n"
"UTC: " << utc << "\n" "UTC: " << utc << "\n"
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
<< Qt::fixed
#else
<< fixed << fixed
#endif
<< qSetFieldWidth (6) << qSetFieldWidth (6)
<< qSetRealNumberPrecision (1) << qSetRealNumberPrecision (1)
<< "Az: " << azmoon << "\n" << "Az: " << azmoon << "\n"

View File

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

View File

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

View File

@ -3,6 +3,8 @@
#define MAINWINDOW_H #define MAINWINDOW_H
#include <QMainWindow> #include <QMainWindow>
#include <QString>
#include <QStringList>
#include <QLabel> #include <QLabel>
#include <QThread> #include <QThread>
#include <QProcess> #include <QProcess>
@ -605,8 +607,7 @@ private:
QString m_rptRcvd; QString m_rptRcvd;
QString m_qsoStart; QString m_qsoStart;
QString m_qsoStop; QString m_qsoStop;
QString m_cmnd; QStringList m_cmndP1;
QString m_cmndP1;
QString m_msgSent0; QString m_msgSent0;
QString m_calls; QString m_calls;
QString m_CQtype; QString m_CQtype;
@ -700,7 +701,7 @@ private:
void genStdMsgs(QString rpt, bool unconditional = false); void genStdMsgs(QString rpt, bool unconditional = false);
void genCQMsg(); void genCQMsg();
void clearDX (); void clearDX ();
void lookup(bool lookupButtonClicked); void lookup();
void ba2msg(QByteArray ba, char* message); void ba2msg(QByteArray ba, char* message);
void msgtype(QString t, QLineEdit* tx); void msgtype(QString t, QLineEdit* tx);
void stub(); void stub();
@ -713,7 +714,7 @@ private:
void pskPost(DecodedText const& decodedtext); void pskPost(DecodedText const& decodedtext);
void displayDialFrequency (); void displayDialFrequency ();
void transmitDisplay (bool); 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 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 locationChange(QString const& location);
void replayDecodes (); void replayDecodes ();