Compare commits

..

59 Commits

Author SHA1 Message Date
Jordan Sherer 95a91fb526 Updated listCopyReverse to support older versions of Qt 2018-08-29 16:00:25 -04:00
Jordan Sherer 081bc0380b Added reply message to configuration 2018-08-29 12:32:09 -04:00
Jordan Sherer 77715347c7 Reordered the query menu 2018-08-29 12:11:32 -04:00
Jordan Sherer 712580d08c Added QSO query for finding a remote station 2018-08-29 12:08:22 -04:00
Jordan Sherer 084765f271 Updated beacon default to 30 minutes 2018-08-29 11:28:26 -04:00
Jordan Sherer d2b7229815 Remove QSY checkbox from settings 2018-08-29 11:17:10 -04:00
Jordan Sherer 63739b9d31 Added scroll wheel support for waterfall. Added hover indicator to make selection of signal easier 2018-08-29 11:06:46 -04:00
Jordan Sherer d1b239201c Removed from callsign from message save log...redundant 2018-08-28 21:06:49 -04:00
Jordan Sherer f06df77db2 Added writing hashed messages to a file on disk 2018-08-28 20:58:39 -04:00
Jordan Sherer 2250589f83 Bump EOL 2018-08-28 16:49:44 -04:00
Jordan Sherer 65a19e4707 Added API entry for logging QSOs 2018-08-28 16:44:21 -04:00
Jordan Sherer c8c4f98610 Added offset to call activity display and sort menu 2018-08-28 16:35:14 -04:00
Jordan Sherer 0ecbbd0da1 Added reply button back into the main window 2018-08-28 16:04:49 -04:00
Jordan Sherer b5cebe41e8 Added caching and restoring band/call/rx activity on band change 2018-08-28 15:45:23 -04:00
Jordan Sherer 83b05df312 Added APRS payload sends to APRS-IS 2018-08-28 15:13:38 -04:00
Jordan Sherer 541bd8bca3 Example email over APRS 2018-08-28 09:45:22 -04:00
Jordan Sherer 565bdb5690 Added function to determine the checksum size needed for a buffered command 2018-08-27 22:04:17 -04:00
Jordan Sherer 7868c3fe70 Added double spacing between message lines 2018-08-27 21:41:22 -04:00
Jordan Sherer adcc728492 Added spotting to APRS-IS for grids larger than 4 characters. Added supporting commands for QTH QTC and GRID 2018-08-27 21:19:38 -04:00
Jordan Sherer 2fa1fcd4f8 Generic label for spotting 2018-08-24 09:39:33 -04:00
Jordan Sherer 8eb0fc327d Added option to enable/disable immediate transmission of directed items 2018-08-24 09:38:00 -04:00
Jordan Sherer e6f83e999b Added a few additional directed message short commands 2018-08-24 09:21:17 -04:00
Jordan Sherer b10ccc370f Added a few additional optional directeds 2018-08-24 00:20:10 -04:00
Jordan Sherer 121ffb48f6 Renamed labeling for sort 2018-08-24 00:11:21 -04:00
Jordan Sherer 4698db27f6 Bump EOL. Ensure grid is also configured before transmit. Optionally show warning message. Display configuration when not configured on application load 2018-08-23 23:59:15 -04:00
Jordan Sherer fe1463b730 Fixed overlay bounds 2018-08-23 17:25:48 -04:00
Jordan Sherer ad154cb2e6 Adjusted 160m frequency 2018-08-23 13:13:28 -04:00
Jordan Sherer 5166b1e0dd Block lower 500Hz from being used to allow frequency separation 2018-08-23 13:10:20 -04:00
Jordan Sherer 5d0e91a5ed Added menu items for band and call activity sorting in the main menu 2018-08-23 12:24:47 -04:00
Jordan Sherer c01238f5e0 Added sorting of band activity and call activity window 2018-08-23 11:59:20 -04:00
Jordan Sherer 726484a05a Remove restriction of grid locator to 4 or 6 chars. Upped to 16 chars 2018-08-22 15:15:30 -04:00
Jordan Sherer b7d2a370f8 Default to spotting 2018-08-17 17:37:43 -04:00
Jordan Sherer 6c8902d802 Tweaks to the directed menu 2018-08-17 11:13:49 -04:00
Jordan Sherer 1002dcbc1b Added enable/disable for UDP API. Added DATA for logging instead of RTTY 2018-08-17 10:07:17 -04:00
Jordan Sherer f2ca9caec7 Added right click menu to the band activity window 2018-08-17 09:35:45 -04:00
Jordan Sherer 96ca7786e5 Fixed issue with background colors 2018-08-17 09:27:31 -04:00
Jordan Sherer eecde27cd8 Open settings if no call has been set 2018-08-17 09:18:49 -04:00
Jordan Sherer d4bb4cf49a Bump to 0.5.0 2018-08-16 17:47:02 -04:00
Jordan Sherer db74c22890 Make sure to initialize the structs 2018-08-16 17:46:53 -04:00
Jordan Sherer 69b90b243a Fixed issue with allcall buffering responses while autoreply is disabled 2018-08-16 16:41:01 -04:00
Jordan Sherer 9bac05c86c Bump version of frequencies settings key to intialize new frequencies 2018-08-16 16:02:44 -04:00
Jordan Sherer fde19eebd8 Updated frequencies to be closer aligned with existing allocations 2018-08-16 15:53:46 -04:00
Jordan Sherer 6b4390fe5c Added warning message with a timeout for automatic band switching 2018-08-16 15:19:43 -04:00
Jordan Sherer ad4e567392 Fixed display of allcalls. No longer red 2018-08-16 11:31:10 -04:00
Jordan Sherer 612df625ed Added ability to change directed message window background color 2018-08-16 11:02:23 -04:00
Jordan Sherer 9475ea7461 Added a couple more frequency options. Decisions. Decisions. 2018-08-16 10:01:25 -04:00
Jordan Sherer 5fad5497d2 Fixed jumping of band activity and call activity tables on update 2018-08-15 23:24:16 -04:00
Jordan Sherer 9815c4dde9 API: Added RX.GET_CALL_SELECTED 2018-08-15 22:31:01 -04:00
Jordan Sherer 60c0f24ef8 Fixed restricted characterset for configuration messages and macros 2018-08-15 22:29:23 -04:00
Jordan Sherer e74e20680a Added alternate frequencies we can switch to for the next build 2018-08-15 21:54:35 -04:00
Jordan Sherer ee44e2e5d7 Fixed issue with QSY during message sending 2018-08-15 20:57:30 -04:00
Jordan Sherer 43574b10b1 Slight modified frequencies for 80m and 12m to avoid PSK 2018-08-15 16:46:19 -04:00
Jordan Sherer 08f046c289 Fixed incorrect labels for frame type enum 2018-08-14 22:26:49 -04:00
Jordan Sherer 5f4a66e916 Added warning message about empty callsign before transmitting 2018-08-14 12:09:14 -04:00
Jordan Sherer bc97c96a5b Added tooltips and better labels 2018-08-14 10:53:30 -04:00
Jordan Sherer 3b1519c603 Bump to v0.4.2 2018-08-12 10:38:59 -04:00
Jordan Sherer f30c2e3858 Fixed configuration of band hopping to reset cached band position after configuration save. Fixed issue with band hopping not working across a date transition 2018-08-12 10:35:19 -04:00
Jordan Sherer c60efba4ca Fixed display of messages that drift more than a few Hz during transmission 2018-08-12 10:03:14 -04:00
Jordan Sherer 5694b96f55 Fixed compound callsigns not displaying in the heard list 2018-08-12 09:23:05 -04:00
26 changed files with 2292 additions and 868 deletions
+258
View File
@@ -0,0 +1,258 @@
#include "APRSISClient.h"
#include <cmath>
#include "Radio.hpp"
#include "varicode.h"
APRSISClient::APRSISClient(QString host, quint16 port, QObject *parent):
QTcpSocket(parent),
m_host(host),
m_port(port)
{
connect(&m_timer, &QTimer::timeout, this, &APRSISClient::sendReports);
m_timer.setInterval(60*1000); // every minute
m_timer.start();
}
quint32 APRSISClient::hashCallsign(QString callsign){
// based on: https://github.com/hessu/aprsc/blob/master/src/passcode.c
QByteArray rootCall = QString(callsign.split("-").first().toUpper()).toLocal8Bit() + '\0';
quint32 hash = 0x73E2;
int i = 0;
int len = rootCall.length();
while(i+1 < len){
hash ^= rootCall.at(i) << 8;
hash ^= rootCall.at(i+1);
i += 2;
}
return hash & 0x7FFF;
}
QString APRSISClient::loginFrame(QString callsign){
auto loginFrame = QString("user %1 pass %2 ver %3\n");
loginFrame = loginFrame.arg(callsign);
loginFrame = loginFrame.arg(hashCallsign(callsign));
loginFrame = loginFrame.arg("FT8Call");
return loginFrame;
}
QList<QStringList> findall(QRegularExpression re, QString content){
int pos = 0;
QList<QStringList> all;
while(pos < content.length()){
auto match = re.match(content, pos);
if(!match.hasMatch()){
break;
}
all.append(match.capturedTexts());
pos = match.capturedEnd();
}
return all;
}
inline long
floordiv (long num, long den)
{
if (0 < (num^den))
return num/den;
else
{
ldiv_t res = ldiv(num,den);
return (res.rem)? res.quot-1
: res.quot;
}
}
// convert an arbitrary length grid locator to a high precision lat/lon
QPair<float, float> APRSISClient::grid2deg(QString locator){
QString grid = locator.toUpper();
float lat = -90;
float lon = -90;
auto lats = findall(QRegularExpression("([A-X])([A-X])"), grid);
auto lons = findall(QRegularExpression("(\\d)(\\d)"), grid);
int valx[22];
int valy[22];
int i = 0;
int tot = 0;
char A = 'A';
foreach(QStringList matched, lats){
char x = matched.at(1).at(0).toLatin1();
char y = matched.at(2).at(0).toLatin1();
valx[i*2] = x-A;
valy[i*2] = y-A;
i++;
tot++;
}
i = 0;
foreach(QStringList matched, lons){
int x = matched.at(1).toInt();
int y = matched.at(2).toInt();
valx[i*2+1]=x;
valy[i*2+1]=y;
i++;
tot++;
}
for(int i = 0; i < tot; i++){
int x = valx[i];
int y = valy[i];
int z = i - 1;
float scale = pow(10, floordiv(-(z-1), 2)) * pow(24, floordiv(-z, 2));
lon += scale * x;
lat += scale * y;
}
lon *= 2;
return {lat, lon};
}
// convert an arbitrary length grid locator to a high precision lat/lon in aprs format
QPair<QString, QString> APRSISClient::grid2aprs(QString grid){
auto geo = APRSISClient::grid2deg(grid);
auto lat = geo.first;
auto lon = geo.second;
QString latDir = "N";
if(lat < 0){
lat *= -1;
latDir = "S";
}
QString lonDir = "E";
if(lon < 0){
lon *= -1;
lonDir = "W";
}
double iLat, fLat, iLon, fLon, iLatMin, fLatMin, iLonMin, fLonMin, iLatSec, iLonSec;
fLat = modf(lat, &iLat);
fLon = modf(lon, &iLon);
fLatMin = modf(fLat * 60, &iLatMin);
fLonMin = modf(fLon * 60, &iLonMin);
iLatSec = round(fLatMin * 60);
iLonSec = round(fLonMin * 60);
if(iLatSec == 60){
iLatMin += 1;
iLatSec = 0;
}
if(iLonSec == 60){
iLonMin += 1;
iLonSec = 0;
}
if(iLatMin == 60){
iLat += 1;
iLatMin = 0;
}
if(iLonMin == 60){
iLon += 1;
iLonMin = 0;
}
double aprsLat = iLat * 100 + iLatMin + (iLatSec / 60.0);
double aprsLon = iLon * 100 + iLonMin + (iLonSec / 60.0);
return {
QString().sprintf("%07.2f%%1", aprsLat).arg(latDir),
QString().sprintf("%08.2f%%1", aprsLon).arg(lonDir)
};
}
void APRSISClient::enqueueSpot(QString theircall, QString grid, quint64 frequency, int snr){
if(m_localCall.isEmpty()) return;
auto geo = APRSISClient::grid2aprs(grid);
auto spotFrame = QString("%1>%2,APRS,TCPIP*:=%3/%4nFT8CALL %5 %6MHz %7dB\n");
spotFrame = spotFrame.arg(theircall);
spotFrame = spotFrame.arg(m_localCall);
spotFrame = spotFrame.arg(geo.first);
spotFrame = spotFrame.arg(geo.second);
spotFrame = spotFrame.arg(m_localGrid.left(4));
spotFrame = spotFrame.arg(Radio::frequency_MHz_string(frequency));
spotFrame = spotFrame.arg(Varicode::formatSNR(snr));
enqueueRaw(spotFrame);
}
void APRSISClient::enqueueMessage(QString tocall, QString message){
if(m_localCall.isEmpty()) return;
auto messageFrame = QString("%1>APRS,TCPIP*::%2:%3\n");
messageFrame = messageFrame.arg(m_localCall);
messageFrame = messageFrame.arg(tocall + QString(" ").repeated(9-tocall.length()));
messageFrame = messageFrame.arg(message);
enqueueRaw(messageFrame);
}
void APRSISClient::enqueueThirdParty(QString theircall, QString payload){
auto frame = QString("%1>%2,APRS,TCPIP*:%3\n");
frame = frame.arg(theircall);
frame = frame.arg(m_localCall);
frame = frame.arg(payload);
enqueueRaw(frame);
}
void APRSISClient::enqueueRaw(QString aprsFrame){
m_frameQueue.enqueue(aprsFrame);
}
void APRSISClient::processQueue(bool disconnect){
if(m_localCall.isEmpty()) return;
// 1. connect (and read)
// 2. login (and read)
// 3. for each raw frame in queue, send
// 4. disconnect
if(state() != QTcpSocket::ConnectedState){
connectToHost(m_host, m_port);
if(!waitForConnected(5000)){
qDebug() << "APRSISClient Connection Error:" << errorString();
return;
}
}
if(write(loginFrame(m_localCall).toLocal8Bit()) == -1){
qDebug() << "APRSISClient Write Login Error:" << errorString();
return;
}
while(!m_frameQueue.isEmpty()){
if(write(m_frameQueue.head().toLocal8Bit()) == -1){
qDebug() << "APRSISClient Write Error:" << errorString();
return;
}
auto frame = m_frameQueue.dequeue();
qDebug() << "APRISISClient Write:" << frame;
}
if(disconnect){
disconnectFromHost();
}
}
+44
View File
@@ -0,0 +1,44 @@
#ifndef APRSISCLIENT_H
#define APRSISCLIENT_H
#include <QTcpSocket>
#include <QQueue>
#include <QPair>
#include <QTimer>
class APRSISClient : public QTcpSocket
{
public:
APRSISClient(QString host, quint16 port, QObject *parent = nullptr);
static quint32 hashCallsign(QString callsign);
static QString loginFrame(QString callsign);
static QPair<float, float> grid2deg(QString grid);
static QPair<QString, QString> grid2aprs(QString grid);
void setLocalStation(QString mycall, QString mygrid){
m_localCall = mycall;
m_localGrid = mygrid;
}
void enqueueSpot(QString theircall, QString grid, quint64 frequency, int snr);
void enqueueMessage(QString tocall, QString message);
void enqueueThirdParty(QString theircall, QString payload);
void enqueueRaw(QString aprsFrame);
void processQueue(bool disconnect=false);
public slots:
void sendReports(){ processQueue(true); }
private:
QString m_localCall;
QString m_localGrid;
QQueue<QString> m_frameQueue;
QString m_host;
quint16 m_port;
QTimer m_timer;
};
#endif // APRSISCLIENT_H
+2
View File
@@ -304,6 +304,8 @@ set (wsjtx_CXXSRCS
messageaveraging.cpp messageaveraging.cpp
WsprTxScheduler.cpp WsprTxScheduler.cpp
varicode.cpp varicode.cpp
SelfDestructMessageBox.cpp
APRSISClient.cpp
mainwindow.cpp mainwindow.cpp
Configuration.cpp Configuration.cpp
main.cpp main.cpp
+91 -39
View File
@@ -196,11 +196,14 @@ namespace
int const combo_box_item_disabled (0); int const combo_box_item_disabled (0);
// QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"}; // QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"};
QRegExp message_alphabet {"[- @A-Za-z0-9+./?#<>]*"}; QRegExp message_alphabet {"[^\\x00-\\x1F]*"};
// Magic numbers for file validation // Magic numbers for file validation
constexpr quint32 qrg_magic {0xadbccbdb}; constexpr quint32 qrg_magic {0xadbccbdb};
constexpr quint32 qrg_version {100}; // M.mm constexpr quint32 qrg_version {102}; // M.mm
// Bump this versioned key every time we need to "reset" our working frequencies...
const char * versionedFrequenciesSettingsKey = "FrequenciesForRegionModes_01";
} }
@@ -451,6 +454,7 @@ private:
Q_SLOT void on_PTT_method_button_group_buttonClicked (int); Q_SLOT void on_PTT_method_button_group_buttonClicked (int);
Q_SLOT void on_station_message_line_edit_textChanged(QString const&); Q_SLOT void on_station_message_line_edit_textChanged(QString const&);
Q_SLOT void on_qth_message_line_edit_textChanged(QString const&); Q_SLOT void on_qth_message_line_edit_textChanged(QString const&);
Q_SLOT void on_reply_message_line_edit_textChanged(QString const&);
Q_SLOT void on_add_macro_line_edit_editingFinished (); Q_SLOT void on_add_macro_line_edit_editingFinished ();
Q_SLOT void delete_macro (); Q_SLOT void delete_macro ();
void delete_selected_macros (QModelIndexList); void delete_selected_macros (QModelIndexList);
@@ -553,14 +557,15 @@ private:
QString my_station_; QString my_station_;
int my_dBm_; int my_dBm_;
QString my_qth_; QString my_qth_;
QString reply_;
int callsign_aging_; int callsign_aging_;
int activity_aging_; int activity_aging_;
QColor color_CQ_; QColor color_CQ_;
QColor next_color_CQ_; QColor next_color_CQ_;
QColor color_MyCall_; QColor color_MyCall_;
QColor next_color_MyCall_; QColor next_color_MyCall_;
QColor color_TxMsg_; QColor color_ReceivedMsg_;
QColor next_color_TxMsg_; QColor next_color_ReceivedMsg_;
QColor color_DXCC_; QColor color_DXCC_;
QColor next_color_DXCC_; QColor next_color_DXCC_;
QColor color_NewCall_; QColor color_NewCall_;
@@ -573,11 +578,12 @@ private:
double txDelay_; double txDelay_;
bool id_after_73_; bool id_after_73_;
bool tx_QSY_allowed_; bool tx_QSY_allowed_;
bool spot_to_psk_reporter_; bool spot_to_reporting_networks_;
bool transmit_directed_;
bool autoreply_off_at_startup_; bool autoreply_off_at_startup_;
bool monitor_off_at_startup_; bool monitor_off_at_startup_;
bool monitor_last_used_; bool monitor_last_used_;
bool log_as_RTTY_; bool log_as_DATA_;
bool report_in_comments_; bool report_in_comments_;
bool prompt_to_log_; bool prompt_to_log_;
bool insert_blank_; bool insert_blank_;
@@ -612,6 +618,7 @@ private:
bool accept_udp_requests_; bool accept_udp_requests_;
bool udpWindowToFront_; bool udpWindowToFront_;
bool udpWindowRestore_; bool udpWindowRestore_;
bool udpEnabled_;
DataMode data_mode_; DataMode data_mode_;
bool pwrBandTxMemory_; bool pwrBandTxMemory_;
bool pwrBandTuneMemory_; bool pwrBandTuneMemory_;
@@ -660,7 +667,7 @@ bool Configuration::use_dynamic_grid() const {return m_->use_dynamic_info_; }
QString Configuration::my_callsign () const {return m_->my_callsign_;} QString Configuration::my_callsign () const {return m_->my_callsign_;}
QColor Configuration::color_CQ () const {return m_->color_CQ_;} QColor Configuration::color_CQ () const {return m_->color_CQ_;}
QColor Configuration::color_MyCall () const {return m_->color_MyCall_;} QColor Configuration::color_MyCall () const {return m_->color_MyCall_;}
QColor Configuration::color_TxMsg () const {return m_->color_TxMsg_;} QColor Configuration::color_ReceivedMsg () const {return m_->color_ReceivedMsg_;}
QColor Configuration::color_DXCC () const {return m_->color_DXCC_;} QColor Configuration::color_DXCC () const {return m_->color_DXCC_;}
QColor Configuration::color_NewCall () const {return m_->color_NewCall_;} QColor Configuration::color_NewCall () const {return m_->color_NewCall_;}
QFont Configuration::text_font () const {return m_->font_;} QFont Configuration::text_font () const {return m_->font_;}
@@ -673,23 +680,24 @@ double Configuration::txDelay() const {return m_->txDelay_;}
qint32 Configuration::RxBandwidth() const {return m_->RxBandwidth_;} qint32 Configuration::RxBandwidth() const {return m_->RxBandwidth_;}
bool Configuration::id_after_73 () const {return m_->id_after_73_;} bool Configuration::id_after_73 () const {return m_->id_after_73_;}
bool Configuration::tx_QSY_allowed () const {return m_->tx_QSY_allowed_;} bool Configuration::tx_QSY_allowed () const {return m_->tx_QSY_allowed_;}
bool Configuration::spot_to_psk_reporter () const bool Configuration::spot_to_reporting_networks () const
{ {
// rig must be open and working to spot externally // rig must be open and working to spot externally
return is_transceiver_online () && m_->spot_to_psk_reporter_; return is_transceiver_online () && m_->spot_to_reporting_networks_;
} }
void Configuration::set_spot_to_psk_reporter (bool spot) void Configuration::set_spot_to_reporting_networks (bool spot)
{ {
if(m_->spot_to_psk_reporter_ != spot){ if(m_->spot_to_reporting_networks_ != spot){
m_->spot_to_psk_reporter_ = spot; m_->spot_to_reporting_networks_ = spot;
m_->write_settings(); m_->write_settings();
} }
} }
bool Configuration::transmit_directed() const { return m_->transmit_directed_; }
bool Configuration::autoreply_off_at_startup () const {return m_->autoreply_off_at_startup_;} bool Configuration::autoreply_off_at_startup () const {return m_->autoreply_off_at_startup_;}
bool Configuration::monitor_off_at_startup () const {return m_->monitor_off_at_startup_;} bool Configuration::monitor_off_at_startup () const {return m_->monitor_off_at_startup_;}
bool Configuration::monitor_last_used () const {return m_->rig_is_dummy_ || m_->monitor_last_used_;} bool Configuration::monitor_last_used () const {return m_->rig_is_dummy_ || m_->monitor_last_used_;}
bool Configuration::log_as_RTTY () const {return m_->log_as_RTTY_;} bool Configuration::log_as_DATA () const {return m_->log_as_DATA_;}
bool Configuration::report_in_comments () const {return m_->report_in_comments_;} bool Configuration::report_in_comments () const {return m_->report_in_comments_;}
bool Configuration::prompt_to_log () const {return m_->prompt_to_log_;} bool Configuration::prompt_to_log () const {return m_->prompt_to_log_;}
bool Configuration::insert_blank () const {return m_->insert_blank_;} bool Configuration::insert_blank () const {return m_->insert_blank_;}
@@ -720,6 +728,7 @@ auto Configuration::n1mm_server_port () const -> port_type {return m_->n1mm_serv
bool Configuration::broadcast_to_n1mm () const {return m_->broadcast_to_n1mm_;} bool Configuration::broadcast_to_n1mm () const {return m_->broadcast_to_n1mm_;}
bool Configuration::udpWindowToFront () const {return m_->udpWindowToFront_;} bool Configuration::udpWindowToFront () const {return m_->udpWindowToFront_;}
bool Configuration::udpWindowRestore () const {return m_->udpWindowRestore_;} bool Configuration::udpWindowRestore () const {return m_->udpWindowRestore_;}
bool Configuration::udpEnabled () const {return m_->udpEnabled_;}
Bands * Configuration::bands () {return &m_->bands_;} Bands * Configuration::bands () {return &m_->bands_;}
Bands const * Configuration::bands () const {return &m_->bands_;} Bands const * Configuration::bands () const {return &m_->bands_;}
StationList * Configuration::stations () {return &m_->stations_;} StationList * Configuration::stations () {return &m_->stations_;}
@@ -865,6 +874,11 @@ QString Configuration::my_qth() const
return m_->my_qth_; return m_->my_qth_;
} }
QString Configuration::reply() const
{
return m_->reply_;
}
int Configuration::callsign_aging() const int Configuration::callsign_aging() const
{ {
return m_->callsign_aging_; return m_->callsign_aging_;
@@ -987,6 +1001,15 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
throw std::runtime_error {"Failed to create samples directory"}; throw std::runtime_error {"Failed to create samples directory"};
} }
QString messages_dir {"messages"};
if (!default_save_directory_.mkpath (messages_dir))
{
MessageBox::critical_message (this, tr ("Failed to create messages directory"),
tr ("path: \"%1\"")
.arg (default_save_directory_.absoluteFilePath (messages_dir)));
throw std::runtime_error {"Failed to create messages directory"};
}
// copy in any new sample files to the sample directory // copy in any new sample files to the sample directory
QDir dest_dir {default_save_directory_}; QDir dest_dir {default_save_directory_};
dest_dir.cd (samples_dir); dest_dir.cd (samples_dir);
@@ -1012,10 +1035,11 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
// validation // validation
// //
ui_->callsign_line_edit->setValidator (new CallsignValidator {this}); ui_->callsign_line_edit->setValidator (new CallsignValidator {this});
ui_->grid_line_edit->setValidator (new MaidenheadLocatorValidator {this}); ui_->grid_line_edit->setValidator (new MaidenheadLocatorValidator {this, MaidenheadLocatorValidator::Length::doubleextended});
ui_->add_macro_line_edit->setValidator (new QRegExpValidator {message_alphabet, this}); ui_->add_macro_line_edit->setValidator (new QRegExpValidator {message_alphabet, this});
ui_->station_message_line_edit->setValidator (new QRegExpValidator {message_alphabet, this}); ui_->station_message_line_edit->setValidator (new QRegExpValidator {message_alphabet, this});
ui_->qth_message_line_edit->setValidator (new QRegExpValidator {message_alphabet, this}); ui_->qth_message_line_edit->setValidator (new QRegExpValidator {message_alphabet, this});
ui_->reply_message_line_edit->setValidator (new QRegExpValidator {message_alphabet, this});
ui_->udp_server_port_spin_box->setMinimum (1); ui_->udp_server_port_spin_box->setMinimum (1);
ui_->udp_server_port_spin_box->setMaximum (std::numeric_limits<port_type>::max ()); ui_->udp_server_port_spin_box->setMaximum (std::numeric_limits<port_type>::max ());
@@ -1235,15 +1259,16 @@ void Configuration::impl::initialize_models ()
ui_->grid_line_edit->setPalette (pal); ui_->grid_line_edit->setPalette (pal);
ui_->auto_switch_bands_check_box->setChecked(auto_switch_bands_); ui_->auto_switch_bands_check_box->setChecked(auto_switch_bands_);
ui_->callsign_line_edit->setText (my_callsign_); ui_->callsign_line_edit->setText (my_callsign_);
ui_->grid_line_edit->setText (my_grid_); ui_->grid_line_edit->setText (my_grid_.toUpper());
ui_->callsign_aging_spin_box->setValue(callsign_aging_); ui_->callsign_aging_spin_box->setValue(callsign_aging_);
ui_->activity_aging_spin_box->setValue(activity_aging_); ui_->activity_aging_spin_box->setValue(activity_aging_);
ui_->station_message_line_edit->setText (my_station_.toUpper()); ui_->station_message_line_edit->setText (my_station_.toUpper());
ui_->qth_message_line_edit->setText (my_qth_.toUpper()); ui_->qth_message_line_edit->setText (my_qth_.toUpper());
ui_->reply_message_line_edit->setText (reply_.toUpper());
ui_->use_dynamic_grid->setChecked(use_dynamic_info_); ui_->use_dynamic_grid->setChecked(use_dynamic_info_);
ui_->labCQ->setStyleSheet(QString("background: %1").arg(color_CQ_.name())); ui_->labCQ->setStyleSheet(QString("background: %1").arg(color_CQ_.name()));
ui_->labMyCall->setStyleSheet(QString("background: %1").arg(color_MyCall_.name())); ui_->labMyCall->setStyleSheet(QString("background: %1").arg(color_MyCall_.name()));
ui_->labTx->setStyleSheet(QString("background: %1").arg(color_TxMsg_.name())); ui_->labTx->setStyleSheet(QString("background: %1").arg(color_ReceivedMsg_.name()));
ui_->labDXCC->setStyleSheet(QString("background: %1").arg(color_DXCC_.name())); ui_->labDXCC->setStyleSheet(QString("background: %1").arg(color_DXCC_.name()));
ui_->labNewCall->setStyleSheet(QString("background: %1").arg(color_NewCall_.name())); ui_->labNewCall->setStyleSheet(QString("background: %1").arg(color_NewCall_.name()));
ui_->CW_id_interval_spin_box->setValue (id_interval_); ui_->CW_id_interval_spin_box->setValue (id_interval_);
@@ -1257,11 +1282,12 @@ void Configuration::impl::initialize_models ()
ui_->azel_path_display_label->setText (azel_directory_.absolutePath ()); ui_->azel_path_display_label->setText (azel_directory_.absolutePath ());
ui_->CW_id_after_73_check_box->setChecked (id_after_73_); ui_->CW_id_after_73_check_box->setChecked (id_after_73_);
ui_->tx_QSY_check_box->setChecked (tx_QSY_allowed_); ui_->tx_QSY_check_box->setChecked (tx_QSY_allowed_);
ui_->psk_reporter_check_box->setChecked (spot_to_psk_reporter_); ui_->psk_reporter_check_box->setChecked (spot_to_reporting_networks_);
ui_->transmit_directed_check_box->setChecked(transmit_directed_);
ui_->autoreply_off_check_box->setChecked (autoreply_off_at_startup_); ui_->autoreply_off_check_box->setChecked (autoreply_off_at_startup_);
ui_->monitor_off_check_box->setChecked (monitor_off_at_startup_); ui_->monitor_off_check_box->setChecked (monitor_off_at_startup_);
ui_->monitor_last_used_check_box->setChecked (monitor_last_used_); ui_->monitor_last_used_check_box->setChecked (monitor_last_used_);
ui_->log_as_RTTY_check_box->setChecked (log_as_RTTY_); ui_->log_as_RTTY_check_box->setChecked (log_as_DATA_);
ui_->stations_table_view->setEnabled(ui_->auto_switch_bands_check_box->isChecked()); ui_->stations_table_view->setEnabled(ui_->auto_switch_bands_check_box->isChecked());
ui_->report_in_comments_check_box->setChecked (report_in_comments_); ui_->report_in_comments_check_box->setChecked (report_in_comments_);
ui_->prompt_to_log_check_box->setChecked (prompt_to_log_); ui_->prompt_to_log_check_box->setChecked (prompt_to_log_);
@@ -1319,6 +1345,7 @@ void Configuration::impl::initialize_models ()
ui_->n1mm_server_port_spin_box->setValue (n1mm_server_port_); ui_->n1mm_server_port_spin_box->setValue (n1mm_server_port_);
ui_->enable_n1mm_broadcast_check_box->setChecked (broadcast_to_n1mm_); ui_->enable_n1mm_broadcast_check_box->setChecked (broadcast_to_n1mm_);
ui_->udpWindowToFront->setChecked(udpWindowToFront_); ui_->udpWindowToFront->setChecked(udpWindowToFront_);
ui_->udpEnable->setChecked(udpEnabled_);
ui_->udpWindowRestore->setChecked(udpWindowRestore_); ui_->udpWindowRestore->setChecked(udpWindowRestore_);
ui_->calibration_intercept_spin_box->setValue (calibration_.intercept); ui_->calibration_intercept_spin_box->setValue (calibration_.intercept);
ui_->calibration_slope_ppm_spin_box->setValue (calibration_.slope_ppm); ui_->calibration_slope_ppm_spin_box->setValue (calibration_.slope_ppm);
@@ -1367,9 +1394,10 @@ void Configuration::impl::read_settings ()
callsign_aging_ = settings_->value ("CallsignAging", 0).toInt (); callsign_aging_ = settings_->value ("CallsignAging", 0).toInt ();
activity_aging_ = settings_->value ("ActivityAging", 2).toInt (); activity_aging_ = settings_->value ("ActivityAging", 2).toInt ();
my_qth_ = settings_->value("MyQTH", QString {}).toString(); my_qth_ = settings_->value("MyQTH", QString {}).toString();
reply_ = settings_->value("Reply", QString {"HW CPY?"}).toString();
next_color_CQ_ = color_CQ_ = settings_->value("colorCQ","#66ff66").toString(); next_color_CQ_ = color_CQ_ = settings_->value("colorCQ","#66ff66").toString();
next_color_MyCall_ = color_MyCall_ = settings_->value("colorMyCall","#ff6666").toString(); next_color_MyCall_ = color_MyCall_ = settings_->value("colorMyCall","#ff6666").toString();
next_color_TxMsg_ = color_TxMsg_ = settings_->value("colorTxMsg","#ffff00").toString(); next_color_ReceivedMsg_ = color_ReceivedMsg_ = settings_->value("colorReceivedMsg","#ffeaa7").toString();
next_color_DXCC_ = color_DXCC_ = settings_->value("colorDXCC","#ff00ff").toString(); next_color_DXCC_ = color_DXCC_ = settings_->value("colorDXCC","#ff00ff").toString();
next_color_NewCall_ = color_NewCall_ = settings_->value("colorNewCall","#ffaaff").toString(); next_color_NewCall_ = color_NewCall_ = settings_->value("colorNewCall","#ffaaff").toString();
@@ -1460,10 +1488,11 @@ void Configuration::impl::read_settings ()
type_2_msg_gen_ = settings_->value ("Type2MsgGen", QVariant::fromValue (Configuration::type_2_msg_3_full)).value<Configuration::Type2MsgGen> (); type_2_msg_gen_ = settings_->value ("Type2MsgGen", QVariant::fromValue (Configuration::type_2_msg_3_full)).value<Configuration::Type2MsgGen> ();
transmit_directed_ = settings_->value ("TransmitDirected", true).toBool();
autoreply_off_at_startup_ = settings_->value ("AutoreplyOFF", false).toBool (); autoreply_off_at_startup_ = settings_->value ("AutoreplyOFF", false).toBool ();
monitor_off_at_startup_ = settings_->value ("MonitorOFF", false).toBool (); monitor_off_at_startup_ = settings_->value ("MonitorOFF", false).toBool ();
monitor_last_used_ = settings_->value ("MonitorLastUsed", false).toBool (); monitor_last_used_ = settings_->value ("MonitorLastUsed", false).toBool ();
spot_to_psk_reporter_ = settings_->value ("PSKReporter", false).toBool (); spot_to_reporting_networks_ = settings_->value ("PSKReporter", true).toBool ();
id_after_73_ = settings_->value ("After73", false).toBool (); id_after_73_ = settings_->value ("After73", false).toBool ();
tx_QSY_allowed_ = settings_->value ("TxQSYAllowed", false).toBool (); tx_QSY_allowed_ = settings_->value ("TxQSYAllowed", false).toBool ();
use_dynamic_info_ = settings_->value ("AutoGrid", false).toBool (); use_dynamic_info_ = settings_->value ("AutoGrid", false).toBool ();
@@ -1474,9 +1503,9 @@ void Configuration::impl::read_settings ()
region_ = settings_->value ("Region", QVariant::fromValue (IARURegions::ALL)).value<IARURegions::Region> (); region_ = settings_->value ("Region", QVariant::fromValue (IARURegions::ALL)).value<IARURegions::Region> ();
if (settings_->contains ("FrequenciesForRegionModes")) if (settings_->contains (versionedFrequenciesSettingsKey))
{ {
auto const& v = settings_->value ("FrequenciesForRegionModes"); auto const& v = settings_->value (versionedFrequenciesSettingsKey);
if (v.isValid ()) if (v.isValid ())
{ {
frequencies_.frequency_list (v.value<FrequencyList_v2::FrequencyItems> ()); frequencies_.frequency_list (v.value<FrequencyList_v2::FrequencyItems> ());
@@ -1493,7 +1522,7 @@ void Configuration::impl::read_settings ()
stations_.station_list (settings_->value ("stations").value<StationList::Stations> ()); stations_.station_list (settings_->value ("stations").value<StationList::Stations> ());
log_as_RTTY_ = settings_->value ("toRTTY", false).toBool (); log_as_DATA_ = settings_->value ("toRTTY", false).toBool ();
report_in_comments_ = settings_->value("dBtoComments", false).toBool (); report_in_comments_ = settings_->value("dBtoComments", false).toBool ();
rig_params_.rig_name = settings_->value ("Rig", TransceiverFactory::basic_transceiver_name_).toString (); rig_params_.rig_name = settings_->value ("Rig", TransceiverFactory::basic_transceiver_name_).toString ();
rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name; rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name;
@@ -1520,7 +1549,7 @@ void Configuration::impl::read_settings ()
miles_ = settings_->value ("Miles", false).toBool (); miles_ = settings_->value ("Miles", false).toBool ();
quick_call_ = settings_->value ("QuickCall", false).toBool (); quick_call_ = settings_->value ("QuickCall", false).toBool ();
disable_TX_on_73_ = settings_->value ("73TxDisable", false).toBool (); disable_TX_on_73_ = settings_->value ("73TxDisable", false).toBool ();
beacon_ = settings_->value ("TxBeacon", 15).toInt (); beacon_ = settings_->value ("TxBeacon", 30).toInt ();
watchdog_ = settings_->value ("TxWatchdog", 0).toInt (); watchdog_ = settings_->value ("TxWatchdog", 0).toInt ();
TX_messages_ = settings_->value ("Tx2QSO", true).toBool (); TX_messages_ = settings_->value ("Tx2QSO", true).toBool ();
enable_VHF_features_ = settings_->value("VHFUHF",false).toBool (); enable_VHF_features_ = settings_->value("VHFUHF",false).toBool ();
@@ -1540,6 +1569,7 @@ void Configuration::impl::read_settings ()
n1mm_server_port_ = settings_->value ("N1MMServerPort", 2333).toUInt (); n1mm_server_port_ = settings_->value ("N1MMServerPort", 2333).toUInt ();
broadcast_to_n1mm_ = settings_->value ("BroadcastToN1MM", false).toBool (); broadcast_to_n1mm_ = settings_->value ("BroadcastToN1MM", false).toBool ();
accept_udp_requests_ = settings_->value ("AcceptUDPRequests", false).toBool (); accept_udp_requests_ = settings_->value ("AcceptUDPRequests", false).toBool ();
udpEnabled_ = settings_->value("UDPEnabled", false).toBool();
udpWindowToFront_ = settings_->value ("udpWindowToFront",false).toBool (); udpWindowToFront_ = settings_->value ("udpWindowToFront",false).toBool ();
udpWindowRestore_ = settings_->value ("udpWindowRestore",false).toBool (); udpWindowRestore_ = settings_->value ("udpWindowRestore",false).toBool ();
calibration_.intercept = settings_->value ("CalibrationIntercept", 0.).toDouble (); calibration_.intercept = settings_->value ("CalibrationIntercept", 0.).toDouble ();
@@ -1558,11 +1588,12 @@ void Configuration::impl::write_settings ()
settings_->setValue ("MyStation", my_station_); settings_->setValue ("MyStation", my_station_);
settings_->setValue ("MyPower", my_dBm_); settings_->setValue ("MyPower", my_dBm_);
settings_->setValue ("MyQTH", my_qth_); settings_->setValue ("MyQTH", my_qth_);
settings_->setValue ("Reply", reply_);
settings_->setValue ("CallsignAging", callsign_aging_); settings_->setValue ("CallsignAging", callsign_aging_);
settings_->setValue ("ActivityAging", activity_aging_); settings_->setValue ("ActivityAging", activity_aging_);
settings_->setValue("colorCQ",color_CQ_); settings_->setValue("colorCQ",color_CQ_);
settings_->setValue("colorMyCall",color_MyCall_); settings_->setValue("colorMyCall",color_MyCall_);
settings_->setValue("colorTxMsg",color_TxMsg_); settings_->setValue("colorReceivedMsg",color_ReceivedMsg_);
settings_->setValue("colorDXCC",color_DXCC_); settings_->setValue("colorDXCC",color_DXCC_);
settings_->setValue("colorNewCall",color_NewCall_); settings_->setValue("colorNewCall",color_NewCall_);
settings_->setValue ("Font", font_.toString ()); settings_->setValue ("Font", font_.toString ());
@@ -1598,16 +1629,17 @@ void Configuration::impl::write_settings ()
settings_->setValue ("AudioInputChannel", AudioDevice::toString (audio_input_channel_)); settings_->setValue ("AudioInputChannel", AudioDevice::toString (audio_input_channel_));
settings_->setValue ("AudioOutputChannel", AudioDevice::toString (audio_output_channel_)); settings_->setValue ("AudioOutputChannel", AudioDevice::toString (audio_output_channel_));
settings_->setValue ("Type2MsgGen", QVariant::fromValue (type_2_msg_gen_)); settings_->setValue ("Type2MsgGen", QVariant::fromValue (type_2_msg_gen_));
settings_->setValue ("TransmitDirected", transmit_directed_);
settings_->setValue ("AutoreplyOFF", autoreply_off_at_startup_); settings_->setValue ("AutoreplyOFF", autoreply_off_at_startup_);
settings_->setValue ("MonitorOFF", monitor_off_at_startup_); settings_->setValue ("MonitorOFF", monitor_off_at_startup_);
settings_->setValue ("MonitorLastUsed", monitor_last_used_); settings_->setValue ("MonitorLastUsed", monitor_last_used_);
settings_->setValue ("PSKReporter", spot_to_psk_reporter_); settings_->setValue ("PSKReporter", spot_to_reporting_networks_);
settings_->setValue ("After73", id_after_73_); settings_->setValue ("After73", id_after_73_);
settings_->setValue ("TxQSYAllowed", tx_QSY_allowed_); settings_->setValue ("TxQSYAllowed", tx_QSY_allowed_);
settings_->setValue ("Macros", macros_.stringList ()); settings_->setValue ("Macros", macros_.stringList ());
settings_->setValue ("FrequenciesForRegionModes", QVariant::fromValue (frequencies_.frequency_list ())); settings_->setValue (versionedFrequenciesSettingsKey, QVariant::fromValue (frequencies_.frequency_list ()));
settings_->setValue ("stations", QVariant::fromValue (stations_.station_list ())); settings_->setValue ("stations", QVariant::fromValue (stations_.station_list ()));
settings_->setValue ("toRTTY", log_as_RTTY_); settings_->setValue ("toRTTY", log_as_DATA_);
settings_->setValue ("dBtoComments", report_in_comments_); settings_->setValue ("dBtoComments", report_in_comments_);
settings_->setValue ("Rig", rig_params_.rig_name); settings_->setValue ("Rig", rig_params_.rig_name);
settings_->setValue ("CATNetworkPort", rig_params_.network_port); settings_->setValue ("CATNetworkPort", rig_params_.network_port);
@@ -1651,6 +1683,7 @@ void Configuration::impl::write_settings ()
settings_->setValue ("N1MMServerPort", n1mm_server_port_); settings_->setValue ("N1MMServerPort", n1mm_server_port_);
settings_->setValue ("BroadcastToN1MM", broadcast_to_n1mm_); settings_->setValue ("BroadcastToN1MM", broadcast_to_n1mm_);
settings_->setValue ("AcceptUDPRequests", accept_udp_requests_); settings_->setValue ("AcceptUDPRequests", accept_udp_requests_);
settings_->setValue ("UDPEnabled", udpEnabled_);
settings_->setValue ("udpWindowToFront", udpWindowToFront_); settings_->setValue ("udpWindowToFront", udpWindowToFront_);
settings_->setValue ("udpWindowRestore", udpWindowRestore_); settings_->setValue ("udpWindowRestore", udpWindowRestore_);
settings_->setValue ("CalibrationIntercept", calibration_.intercept); settings_->setValue ("CalibrationIntercept", calibration_.intercept);
@@ -1928,10 +1961,12 @@ void Configuration::impl::accept ()
color_CQ_ = next_color_CQ_; color_CQ_ = next_color_CQ_;
color_MyCall_ = next_color_MyCall_; color_MyCall_ = next_color_MyCall_;
color_TxMsg_ = next_color_TxMsg_; color_ReceivedMsg_ = next_color_ReceivedMsg_;
color_DXCC_ = next_color_DXCC_; color_DXCC_ = next_color_DXCC_;
color_NewCall_ = next_color_NewCall_; color_NewCall_ = next_color_NewCall_;
Q_EMIT self_->colors_changed();
rig_params_ = temp_rig_params; // now we can go live with the rig rig_params_ = temp_rig_params; // now we can go live with the rig
// related configuration parameters // related configuration parameters
rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name; rig_is_dummy_ = TransceiverFactory::basic_transceiver_name_ == rig_params_.rig_name;
@@ -2014,11 +2049,12 @@ void Configuration::impl::accept ()
my_callsign_ = ui_->callsign_line_edit->text (); my_callsign_ = ui_->callsign_line_edit->text ();
my_grid_ = ui_->grid_line_edit->text (); my_grid_ = ui_->grid_line_edit->text ();
my_station_ = ui_->station_message_line_edit->text().toUpper(); my_station_ = ui_->station_message_line_edit->text().toUpper();
reply_ = ui_->reply_message_line_edit->text().toUpper();
my_dBm_ = ui_->station_power_combo_box->currentData().toInt(); my_dBm_ = ui_->station_power_combo_box->currentData().toInt();
my_qth_ = ui_->qth_message_line_edit->text().toUpper(); my_qth_ = ui_->qth_message_line_edit->text().toUpper();
callsign_aging_ = ui_->callsign_aging_spin_box->value(); callsign_aging_ = ui_->callsign_aging_spin_box->value();
activity_aging_ = ui_->activity_aging_spin_box->value(); activity_aging_ = ui_->activity_aging_spin_box->value();
spot_to_psk_reporter_ = ui_->psk_reporter_check_box->isChecked (); spot_to_reporting_networks_ = ui_->psk_reporter_check_box->isChecked ();
id_interval_ = ui_->CW_id_interval_spin_box->value (); id_interval_ = ui_->CW_id_interval_spin_box->value ();
ntrials_ = ui_->sbNtrials->value (); ntrials_ = ui_->sbNtrials->value ();
txDelay_ = ui_->sbTxDelay->value (); txDelay_ = ui_->sbTxDelay->value ();
@@ -2027,11 +2063,12 @@ void Configuration::impl::accept ()
RxBandwidth_ = ui_->sbBandwidth->value (); RxBandwidth_ = ui_->sbBandwidth->value ();
id_after_73_ = ui_->CW_id_after_73_check_box->isChecked (); id_after_73_ = ui_->CW_id_after_73_check_box->isChecked ();
tx_QSY_allowed_ = ui_->tx_QSY_check_box->isChecked (); tx_QSY_allowed_ = ui_->tx_QSY_check_box->isChecked ();
transmit_directed_ = ui_->transmit_directed_check_box->isChecked();
autoreply_off_at_startup_ = ui_->autoreply_off_check_box->isChecked (); autoreply_off_at_startup_ = ui_->autoreply_off_check_box->isChecked ();
monitor_off_at_startup_ = ui_->monitor_off_check_box->isChecked (); monitor_off_at_startup_ = ui_->monitor_off_check_box->isChecked ();
monitor_last_used_ = ui_->monitor_last_used_check_box->isChecked (); monitor_last_used_ = ui_->monitor_last_used_check_box->isChecked ();
type_2_msg_gen_ = static_cast<Type2MsgGen> (ui_->type_2_msg_gen_combo_box->currentIndex ()); type_2_msg_gen_ = static_cast<Type2MsgGen> (ui_->type_2_msg_gen_combo_box->currentIndex ());
log_as_RTTY_ = ui_->log_as_RTTY_check_box->isChecked (); log_as_DATA_ = ui_->log_as_RTTY_check_box->isChecked ();
report_in_comments_ = ui_->report_in_comments_check_box->isChecked (); report_in_comments_ = ui_->report_in_comments_check_box->isChecked ();
prompt_to_log_ = ui_->prompt_to_log_check_box->isChecked (); prompt_to_log_ = ui_->prompt_to_log_check_box->isChecked ();
insert_blank_ = ui_->insert_blank_check_box->isChecked (); insert_blank_ = ui_->insert_blank_check_box->isChecked ();
@@ -2060,11 +2097,15 @@ void Configuration::impl::accept ()
pwrBandTxMemory_ = ui_->checkBoxPwrBandTxMemory->isChecked (); pwrBandTxMemory_ = ui_->checkBoxPwrBandTxMemory->isChecked ();
pwrBandTuneMemory_ = ui_->checkBoxPwrBandTuneMemory->isChecked (); pwrBandTuneMemory_ = ui_->checkBoxPwrBandTuneMemory->isChecked ();
opCall_=ui_->opCallEntry->text(); opCall_=ui_->opCallEntry->text();
auto newUdpEnabled = ui_->udpEnable->isChecked();
auto new_server = ui_->udp_server_line_edit->text (); auto new_server = ui_->udp_server_line_edit->text ();
if (new_server != udp_server_name_) if (new_server != udp_server_name_ || newUdpEnabled != udpEnabled_)
{ {
udp_server_name_ = new_server; udp_server_name_ = new_server;
Q_EMIT self_->udp_server_changed (new_server); udpEnabled_ = newUdpEnabled;
Q_EMIT self_->udp_server_changed (udpEnabled_ ? new_server : "");
} }
auto new_port = ui_->udp_server_port_spin_box->value (); auto new_port = ui_->udp_server_port_spin_box->value ();
@@ -2084,6 +2125,7 @@ void Configuration::impl::accept ()
udpWindowToFront_ = ui_->udpWindowToFront->isChecked (); udpWindowToFront_ = ui_->udpWindowToFront->isChecked ();
udpWindowRestore_ = ui_->udpWindowRestore->isChecked (); udpWindowRestore_ = ui_->udpWindowRestore->isChecked ();
if (macros_.stringList () != next_macros_.stringList ()) if (macros_.stringList () != next_macros_.stringList ())
{ {
macros_.setStringList (next_macros_.stringList ()); macros_.setStringList (next_macros_.stringList ());
@@ -2101,6 +2143,8 @@ void Configuration::impl::accept ()
{ {
stations_.station_list(next_stations_.station_list ()); stations_.station_list(next_stations_.station_list ());
stations_.sort (StationList::switch_at_column); stations_.sort (StationList::switch_at_column);
Q_EMIT self_->band_schedule_changed(this->stations_);
} }
if (ui_->use_dynamic_grid->isChecked() && !use_dynamic_info_ ) if (ui_->use_dynamic_grid->isChecked() && !use_dynamic_info_ )
@@ -2143,7 +2187,7 @@ void Configuration::impl::on_font_push_button_clicked ()
void Configuration::impl::on_pbCQmsg_clicked() void Configuration::impl::on_pbCQmsg_clicked()
{ {
auto new_color = QColorDialog::getColor(next_color_CQ_, this, "CQ Messages Color"); auto new_color = QColorDialog::getColor(next_color_CQ_, this, "CQ and BEACON Messages Color");
if (new_color.isValid ()) if (new_color.isValid ())
{ {
next_color_CQ_ = new_color; next_color_CQ_ = new_color;
@@ -2153,7 +2197,7 @@ void Configuration::impl::on_pbCQmsg_clicked()
void Configuration::impl::on_pbMyCall_clicked() void Configuration::impl::on_pbMyCall_clicked()
{ {
auto new_color = QColorDialog::getColor(next_color_MyCall_, this, "My Call Messages Color"); auto new_color = QColorDialog::getColor(next_color_MyCall_, this, "Directed Messages Color");
if (new_color.isValid ()) if (new_color.isValid ())
{ {
next_color_MyCall_ = new_color; next_color_MyCall_ = new_color;
@@ -2163,11 +2207,11 @@ void Configuration::impl::on_pbMyCall_clicked()
void Configuration::impl::on_pbTxMsg_clicked() void Configuration::impl::on_pbTxMsg_clicked()
{ {
auto new_color = QColorDialog::getColor(next_color_TxMsg_, this, "Tx Messages Color"); auto new_color = QColorDialog::getColor(next_color_ReceivedMsg_, this, "Received Messages Textarea Color");
if (new_color.isValid ()) if (new_color.isValid ())
{ {
next_color_TxMsg_ = new_color; next_color_ReceivedMsg_ = new_color;
ui_->labTx->setStyleSheet(QString("background: %1").arg(next_color_TxMsg_.name())); ui_->labTx->setStyleSheet(QString("background: %1").arg(next_color_ReceivedMsg_.name()));
} }
} }
@@ -2194,7 +2238,7 @@ void Configuration::impl::on_pbNewCall_clicked()
void Configuration::impl::on_decoded_text_font_push_button_clicked () void Configuration::impl::on_decoded_text_font_push_button_clicked ()
{ {
next_decoded_text_font_ = QFontDialog::getFont (0, decoded_text_font_ , this next_decoded_text_font_ = QFontDialog::getFont (0, decoded_text_font_ , this
, tr ("WSJT-X Decoded Text Font Chooser") , tr ("Font Chooser")
#if QT_VERSION >= 0x050201 #if QT_VERSION >= 0x050201
, QFontDialog::MonospacedFonts , QFontDialog::MonospacedFonts
#endif #endif
@@ -2318,6 +2362,14 @@ void Configuration::impl::on_qth_message_line_edit_textChanged(QString const &te
} }
} }
void Configuration::impl::on_reply_message_line_edit_textChanged(QString const &text)
{
QString upper = text.toUpper();
if(text != upper){
ui_->reply_message_line_edit->setText (upper);
}
}
void Configuration::impl::on_add_macro_line_edit_editingFinished () void Configuration::impl::on_add_macro_line_edit_editingFinished ()
{ {
ui_->add_macro_line_edit->setText (ui_->add_macro_line_edit->text ().toUpper ()); ui_->add_macro_line_edit->setText (ui_->add_macro_line_edit->text ().toUpper ());
+10 -4
View File
@@ -102,6 +102,7 @@ public:
int activity_aging() const; int activity_aging() const;
int callsign_aging() const; int callsign_aging() const;
QString my_qth () const; QString my_qth () const;
QString reply () const;
QFont text_font () const; QFont text_font () const;
QFont decoded_text_font () const; QFont decoded_text_font () const;
qint32 id_interval () const; qint32 id_interval () const;
@@ -112,12 +113,13 @@ public:
double txDelay() const; double txDelay() const;
bool id_after_73 () const; bool id_after_73 () const;
bool tx_QSY_allowed () const; bool tx_QSY_allowed () const;
bool spot_to_psk_reporter () const; bool spot_to_reporting_networks () const;
void set_spot_to_psk_reporter (bool); void set_spot_to_reporting_networks (bool);
bool transmit_directed() const;
bool autoreply_off_at_startup () const; bool autoreply_off_at_startup () const;
bool monitor_off_at_startup () const; bool monitor_off_at_startup () const;
bool monitor_last_used () const; bool monitor_last_used () const;
bool log_as_RTTY () const; bool log_as_DATA () const;
bool report_in_comments () const; bool report_in_comments () const;
bool prompt_to_log () const; bool prompt_to_log () const;
bool insert_blank () const; bool insert_blank () const;
@@ -156,6 +158,7 @@ public:
bool accept_udp_requests () const; bool accept_udp_requests () const;
bool udpWindowToFront () const; bool udpWindowToFront () const;
bool udpWindowRestore () const; bool udpWindowRestore () const;
bool udpEnabled () const;
Bands * bands (); Bands * bands ();
Bands const * bands () const; Bands const * bands () const;
IARURegions::Region region () const; IARURegions::Region region () const;
@@ -172,7 +175,7 @@ public:
Type2MsgGen type_2_msg_gen () const; Type2MsgGen type_2_msg_gen () const;
QColor color_CQ () const; QColor color_CQ () const;
QColor color_MyCall () const; QColor color_MyCall () const;
QColor color_TxMsg () const; QColor color_ReceivedMsg () const;
QColor color_DXCC () const; QColor color_DXCC () const;
QColor color_NewCall () const; QColor color_NewCall () const;
bool pwrBandTxMemory () const; bool pwrBandTxMemory () const;
@@ -267,6 +270,7 @@ public:
// //
Q_SIGNAL void text_font_changed (QFont); Q_SIGNAL void text_font_changed (QFont);
Q_SIGNAL void decoded_text_font_changed (QFont); Q_SIGNAL void decoded_text_font_changed (QFont);
Q_SIGNAL void colors_changed ();
// //
// This signal is emitted when the UDP server changes // This signal is emitted when the UDP server changes
@@ -274,6 +278,8 @@ public:
Q_SIGNAL void udp_server_changed (QString const& udp_server); Q_SIGNAL void udp_server_changed (QString const& udp_server);
Q_SIGNAL void udp_server_port_changed (port_type server_port); Q_SIGNAL void udp_server_port_changed (port_type server_port);
// This signal is emitted when the band schedule changes
Q_SIGNAL void band_schedule_changed (StationList &stations);
// //
// These signals are emitted and reflect transceiver state changes // These signals are emitted and reflect transceiver state changes
+487 -459
View File
File diff suppressed because it is too large Load Diff
+8 -8
View File
@@ -26,16 +26,16 @@ namespace
{ {
FrequencyList_v2::FrequencyItems const default_frequency_list = FrequencyList_v2::FrequencyItems const default_frequency_list =
{ {
{ 1838000, Modes::FT8CALL, IARURegions::ALL}, // 2 below { 1842000, Modes::FT8CALL, IARURegions::ALL}, // 2 above
{ 3580000, Modes::FT8CALL, IARURegions::ALL}, // 7 above { 3578000, Modes::FT8CALL, IARURegions::ALL}, // 5 above
{ 7080000, Modes::FT8CALL, IARURegions::ALL}, // 7 above { 7078000, Modes::FT8CALL, IARURegions::ALL}, // 4 above
{10130000, Modes::FT8CALL, IARURegions::ALL}, // 6 below {10130000, Modes::FT8CALL, IARURegions::ALL}, // 6 below
{14080000, Modes::FT8CALL, IARURegions::ALL}, // 6 above {14078000, Modes::FT8CALL, IARURegions::ALL}, // 4 above
{18104000, Modes::FT8CALL, IARURegions::ALL}, // 4 above {18104000, Modes::FT8CALL, IARURegions::ALL}, // 4 above
{21080000, Modes::FT8CALL, IARURegions::ALL}, // 6 above {21078000, Modes::FT8CALL, IARURegions::ALL}, // 4 above
{24920000, Modes::FT8CALL, IARURegions::ALL}, // 5 above {24922000, Modes::FT8CALL, IARURegions::ALL}, // 9 above
{28080000, Modes::FT8CALL, IARURegions::ALL}, // 6 above {28078000, Modes::FT8CALL, IARURegions::ALL}, // 4 above
{50300000, Modes::FT8CALL, IARURegions::ALL}, // 13 below {50318000, Modes::FT8CALL, IARURegions::ALL}, // 5 above
}; };
} }
+1 -1
View File
@@ -11,7 +11,7 @@ class MaidenheadLocatorValidator final
: public QValidator : public QValidator
{ {
public: public:
enum class Length {field = 2, square = 4, subsquare = 6, extended = 8}; enum class Length {field = 2, square = 4, subsquare = 6, extended = 8, doubleextended = 16};
MaidenheadLocatorValidator (QObject * parent = nullptr MaidenheadLocatorValidator (QObject * parent = nullptr
, Length length = Length::subsquare , Length length = Length::subsquare
, Length required = Length::square); , Length required = Length::square);
+1
View File
@@ -329,6 +329,7 @@ auto MessageClient::server_port () const -> port_type
void MessageClient::set_server (QString const& server) void MessageClient::set_server (QString const& server)
{ {
qDebug() << "server changed to" << server;
m_->server_.clear (); m_->server_.clear ();
m_->server_string_ = server; m_->server_string_ = server;
if (!server.isEmpty ()) if (!server.isEmpty ())
+40
View File
@@ -0,0 +1,40 @@
#include "SelfDestructMessageBox.h"
SelfDestructMessageBox::SelfDestructMessageBox(
int timeout,
const QString& title,
const QString& text,
QMessageBox::Icon icon,
QMessageBox::StandardButtons buttons,
QMessageBox::StandardButton defaultButton,
QWidget* parent,
Qt::WindowFlags flags)
: QMessageBox(icon, title, text, buttons, parent, flags),
m_timeout(timeout),
m_text(text)
{
connect(&m_timer, &QTimer::timeout, this, &SelfDestructMessageBox::tick);
m_timer.setInterval(1000);
setDefaultButton(defaultButton);
connect(this->defaultButton(), &QPushButton::clicked, this, &SelfDestructMessageBox::accept);
}
void SelfDestructMessageBox::showEvent(QShowEvent* event)
{
tick();
m_timer.start();
QMessageBox::showEvent(event);
}
void SelfDestructMessageBox::tick(){
m_timeout--;
if(m_timeout){
setText(m_text.arg(m_timeout));
return;
}
m_timer.stop();
accept();
}
+35
View File
@@ -0,0 +1,35 @@
#ifndef SELFDESTRUCTMESSAGEBOX_H
#define SELFDESTRUCTMESSAGEBOX_H
#include <QWidget>
#include <QMessageBox>
#include <QPushButton>
#include <QString>
#include <QTimer>
class SelfDestructMessageBox : public QMessageBox
{
Q_OBJECT
public:
SelfDestructMessageBox(int timeout,
const QString& title,
const QString& text,
QMessageBox::Icon icon,
QMessageBox::StandardButtons buttons = QMessageBox::Ok | QMessageBox::Cancel,
QMessageBox::StandardButton defaultButton = QMessageBox::Ok,
QWidget* parent = nullptr,
Qt::WindowFlags flags = 0);
void showEvent(QShowEvent* event) override;
private slots:
void tick();
private:
int m_timeout;
QString m_text;
QTimer m_timer;
};
#endif // SELFDESTRUCTMESSAGEBOX_H
+2 -2
View File
@@ -1,6 +1,6 @@
# Version number components # Version number components
set (WSJTX_VERSION_MAJOR 0) set (WSJTX_VERSION_MAJOR 0)
set (WSJTX_VERSION_MINOR 4) set (WSJTX_VERSION_MINOR 5)
set (WSJTX_VERSION_PATCH 1) set (WSJTX_VERSION_PATCH 0)
set (WSJTX_RC 0) # release candidate number, comment out or zero for development versions set (WSJTX_RC 0) # release candidate number, comment out or zero for development versions
set (WSJTX_VERSION_IS_RELEASE 0) # set to 1 for final release build set (WSJTX_VERSION_IS_RELEASE 0) # set to 1 for final release build
+69
View File
@@ -0,0 +1,69 @@
import socket
KKEY = 0x73e2
def do_hash(callsign):
rootCall = callsign.split("-")[0].upper() + '\0'
hash = KKEY
i = 0
length = len(rootCall)
while (i+1 < length):
hash ^= ord(rootCall[i])<<8
hash ^= ord(rootCall[i+1])
i += 2
return int(hash & 0x7fff)
HOST = 'rotate.aprs2.net'
PORT = 14580
print "Connecting..."
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
print "Connected..."
data = s.recv(1024)
print data
call = 'KN4CRD'
pw = do_hash(call)
ver = "FT8Call"
login = "user {} pass {} ver {}\n".format(call, pw, ver)
s.send(login)
print "Login sent...", login
data = s.recv(1024)
print data
if 0:
message = "KN4CRD>OH8STN,APRS,TCPIP*::EMAIL-2 :KN4CRD@GMAIL.COM TESTING!{04}\n"
s.send(message)
if 0:
message = "{}>APRS,TCPIP*::EMAIL-2 :kn4crd@gmail.com testing456{{01}}\n".format(call)
message = "KN4CRD>APRS,TCPIP*::EMAIL-2 :KN4CRD@GMAIL.COM TESTING!{02}\n"
s.send(message)
if 0:
payload = ":This is a test message"
message = "{}>APRS,TCPIP*::{} {}\n".format(call, call, payload)
s.send(message)
if 1:
position = "=3352.45N/08422.71Wn"
status = "FT8CALL VIA XX9XXX/XXXX 14.082500MHz -20dB"
payload = "".join((position, status))
message = "{}>OH8STN,APRS,TCPIP*:{}\n".format(call, payload)
s.send(message)
print "Spot sent...", message
data = s.recv(1024)
print data
s.close()
+2 -2
View File
@@ -277,7 +277,7 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 txFreq, void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 txFreq,
QColor color_TxMsg, bool bFastMode) QColor color_ReceivedMsg, bool bFastMode)
{ {
QString t1=" @ "; QString t1=" @ ";
if(modeTx=="FT8") t1=" ~ "; if(modeTx=="FT8") t1=" ~ ";
@@ -297,7 +297,7 @@ void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 tx
t = QDateTime::currentDateTimeUtc().toString("hhmm") + \ t = QDateTime::currentDateTimeUtc().toString("hhmm") + \
" Tx " + t2 + t1 + text; " Tx " + t2 + t1 + text;
} }
appendText (t, color_TxMsg); appendText (t, color_ReceivedMsg);
} }
void DisplayText::displayQSY(QString text) void DisplayText::displayQSY(QString text)
+1 -1
View File
@@ -26,7 +26,7 @@ public:
LogBook const& logBook, QColor color_CQ, QColor color_MyCall, LogBook const& logBook, QColor color_CQ, QColor color_MyCall,
QColor color_DXCC, QColor color_NewCall, bool ppfx, bool bCQonly=false); QColor color_DXCC, QColor color_NewCall, bool ppfx, bool bCQonly=false);
void displayTransmittedText(QString text, QString modeTx, qint32 txFreq, void displayTransmittedText(QString text, QString modeTx, qint32 txFreq,
QColor color_TxMsg, bool bFastMode); QColor color_ReceivedMsg, bool bFastMode);
void displayQSY(QString text); void displayQSY(QString text);
void displayFoxToBeCalled(QString t, QColor bg); void displayFoxToBeCalled(QString t, QColor bg);
+1 -1
View File
@@ -75,7 +75,7 @@ void LogQSO::initLogQSO(QString const& hisCall, QString const& hisGrid, QString
if(rptRcvd!="") t+=" Rcvd: " + rptRcvd; if(rptRcvd!="") t+=" Rcvd: " + rptRcvd;
ui->comments->setText(t); ui->comments->setText(t);
} }
if(toRTTY) mode="RTTY"; if(toRTTY) mode="DATA";
ui->mode->setText(mode); ui->mode->setText(mode);
ui->sent->setText(rptSent); ui->sent->setText(rptSent);
ui->rcvd->setText(rptRcvd); ui->rcvd->setText(rptRcvd);
+994 -310
View File
File diff suppressed because it is too large Load Diff
+34 -8
View File
@@ -44,6 +44,7 @@
#include "qpriorityqueue.h" #include "qpriorityqueue.h"
#include "varicode.h" #include "varicode.h"
#include "MessageClient.hpp" #include "MessageClient.hpp"
#include "APRSISClient.h"
#define NUM_JT4_SYMBOLS 206 //(72+31)*2, embedded sync #define NUM_JT4_SYMBOLS 206 //(72+31)*2, embedded sync
#define NUM_JT65_SYMBOLS 126 //63 data + 63 sync #define NUM_JT65_SYMBOLS 126 //63 data + 63 sync
@@ -132,14 +133,19 @@ public slots:
void logCallActivity(CallDetail d, bool spot=true); void logCallActivity(CallDetail d, bool spot=true);
QString lookupCallInCompoundCache(QString const &call); QString lookupCallInCompoundCache(QString const &call);
void cacheActivity(QString key);
void restoreActivity(QString key);
void clearActivity(); void clearActivity();
void displayTextForFreq(QString text, int freq, QDateTime date, bool isTx, bool isNewLine, bool isLast); void displayTextForFreq(QString text, int freq, QDateTime date, bool isTx, bool isNewLine, bool isLast);
void writeNoticeTextToUI(QDateTime date, QString text);
int writeMessageTextToUI(QDateTime date, QString text, int freq, bool bold, int block=-1); int writeMessageTextToUI(QDateTime date, QString text, int freq, bool bold, int block=-1);
void addMessageText(QString text, bool clear=false); bool isMessageQueuedForTransmit();
void addMessageText(QString text, bool clear=false, bool selectFirstPlaceholder=false);
void enqueueMessage(int priority, QString message, int freq, Callback c); void enqueueMessage(int priority, QString message, int freq, Callback c);
void resetMessage(); void resetMessage();
void resetMessageUI(); void resetMessageUI();
void restoreMessage(); void restoreMessage();
bool ensureCallsignSet(bool alert=true);
void createMessage(QString const& text); void createMessage(QString const& text);
void createMessageTransmitQueue(QString const& text); void createMessageTransmitQueue(QString const& text);
void resetMessageTransmitQueue(); void resetMessageTransmitQueue();
@@ -164,7 +170,7 @@ private slots:
void on_actionShow_Waterfall_triggered(bool checked); void on_actionShow_Waterfall_triggered(bool checked);
void on_actionReset_Window_Sizes_triggered(); void on_actionReset_Window_Sizes_triggered();
void on_actionSettings_triggered(); void on_actionSettings_triggered();
void preparePSKReporter(); void prepareSpotting();
void on_spotButton_clicked(bool checked); void on_spotButton_clicked(bool checked);
void on_monitorButton_clicked (bool); void on_monitorButton_clicked (bool);
void on_actionAbout_triggered(); void on_actionAbout_triggered();
@@ -252,9 +258,14 @@ private slots:
void on_rbFreeText_clicked(bool checked); void on_rbFreeText_clicked(bool checked);
void on_clearAction_triggered(QObject * sender); void on_clearAction_triggered(QObject * sender);
void on_cqMacroButton_clicked(); void on_cqMacroButton_clicked();
void on_qtcMacroButton_clicked(); void on_replyMacroButton_clicked();
void on_qthMacroButton_clicked(); void on_qthMacroButton_clicked();
void buildQueryMenu(QMenu *); void setSortBy(QString key, QString value);
QString getSortBy(QString key, QString defaultValue);
void buildSortByMenu(QMenu * menu, QString key, QString defaultValue, QList<QPair<QString, QString> > values);
void buildBandActivitySortByMenu(QMenu * menu);
void buildCallActivitySortByMenu(QMenu * menu);
void buildQueryMenu(QMenu *, QString callsign);
void on_queryButton_pressed(); void on_queryButton_pressed();
void on_macrosMacroButton_pressed(); void on_macrosMacroButton_pressed();
void on_tableWidgetRXAll_cellClicked(int row, int col); void on_tableWidgetRXAll_cellClicked(int row, int col);
@@ -277,7 +288,7 @@ private slots:
void pauseBacon(); void pauseBacon();
void checkBacon(); void checkBacon();
void prepareBacon(); void prepareBacon();
QString calculateDistance(QString const& grid); QString calculateDistance(QString const& grid, int *pDistance=nullptr);
void on_rptSpinBox_valueChanged(int n); void on_rptSpinBox_valueChanged(int n);
void killFile(); void killFile();
void on_tuneButton_clicked (bool); void on_tuneButton_clicked (bool);
@@ -353,6 +364,7 @@ private slots:
void on_sbMax_dB_valueChanged(int n); void on_sbMax_dB_valueChanged(int n);
void on_pbFoxReset_clicked(); void on_pbFoxReset_clicked();
void on_comboBoxHoundSort_activated (int index); void on_comboBoxHoundSort_activated (int index);
void expiry_warning_message ();
void not_GA_warning_message (); void not_GA_warning_message ();
private: private:
@@ -722,6 +734,12 @@ private:
} }
}; };
struct CachedDirectedType {
bool isAllcall;
QDateTime date;
};
QMap<QString, QVariant> m_sortCache; // table key -> sort by
QPriorityQueue<PrioritizedMessage> m_txMessageQueue; // messages to be sent QPriorityQueue<PrioritizedMessage> m_txMessageQueue; // messages to be sent
QQueue<QString> m_txFrameQueue; // frames to be sent QQueue<QString> m_txFrameQueue; // frames to be sent
QQueue<ActivityDetail> m_rxActivityQueue; // all rx activity queue QQueue<ActivityDetail> m_rxActivityQueue; // all rx activity queue
@@ -730,12 +748,17 @@ private:
QMap<QString, QString> m_compoundCallCache; // base callsign -> compound callsign QMap<QString, QString> m_compoundCallCache; // base callsign -> compound callsign
QCache<QString, QDateTime> m_txAllcallCommandCache; // callsign -> last tx QCache<QString, QDateTime> m_txAllcallCommandCache; // callsign -> last tx
QCache<int, QDateTime> m_rxRecentCache; // freq -> last rx QCache<int, QDateTime> m_rxRecentCache; // freq -> last rx
QCache<int, QDateTime> m_rxDirectedCache; // freq -> last directed rx QCache<int, CachedDirectedType> m_rxDirectedCache; // freq -> last directed rx
QCache<QString, int> m_rxCallCache; // call -> last freq seen QCache<QString, int> m_rxCallCache; // call -> last freq seen
QMap<int, int> m_rxFrameBlockNumbers; // freq -> block QMap<int, int> m_rxFrameBlockNumbers; // freq -> block
QMap<int, QList<ActivityDetail>> m_bandActivity; // freq -> [(text, last timestamp), ...] QMap<int, QList<ActivityDetail>> m_bandActivity; // freq -> [(text, last timestamp), ...]
QMap<int, MessageBuffer> m_messageBuffer; // freq -> (cmd, [frames, ...]) QMap<int, MessageBuffer> m_messageBuffer; // freq -> (cmd, [frames, ...])
QMap<QString, CallDetail> m_callActivity; // call -> (last freq, last timestamp) QMap<QString, CallDetail> m_callActivity; // call -> (last freq, last timestamp)
QMap<QString, QMap<QString, CallDetail>> m_callActivityCache; // band -> call activity
QMap<QString, QMap<int, QList<ActivityDetail>>> m_bandActivityCache; // band -> band activity
QMap<QString, QString> m_rxTextCache; // band -> rx text
QSet<QString> m_callSeenBeacon; // call QSet<QString> m_callSeenBeacon; // call
int m_previousFreq; int m_previousFreq;
bool m_shouldRestoreFreq; bool m_shouldRestoreFreq;
@@ -791,6 +814,7 @@ private:
QTimer m_heartbeat; QTimer m_heartbeat;
MessageClient * m_messageClient; MessageClient * m_messageClient;
PSK_Reporter *psk_Reporter; PSK_Reporter *psk_Reporter;
APRSISClient * m_aprsClient;
DisplayManual m_manual; DisplayManual m_manual;
QHash<QString, QVariant> m_pwrBandTxMemory; // Remembers power level by band QHash<QString, QVariant> m_pwrBandTxMemory; // Remembers power level by band
QHash<QString, QVariant> m_pwrBandTuneMemory; // Remembers power level by band for tuning QHash<QString, QVariant> m_pwrBandTuneMemory; // Remembers power level by band for tuning
@@ -817,8 +841,10 @@ private:
void transmit (double snr = 99.); void transmit (double snr = 99.);
void rigFailure (QString const& reason); void rigFailure (QString const& reason);
void pskSetLocal (); void pskSetLocal ();
void aprsSetLocal ();
void pskPost(DecodedText const& decodedtext); void pskPost(DecodedText const& decodedtext);
void pskLogReport(QString mode, int offset, int snr, QString callsign, QString grid); void pskLogReport(QString mode, int offset, int snr, QString callsign, QString grid);
void aprsLogReport(int offset, int snr, QString callsign, QString grid);
Radio::Frequency dialFrequency(); Radio::Frequency dialFrequency();
void displayDialFrequency (); void displayDialFrequency ();
void transmitDisplay (bool); void transmitDisplay (bool);
@@ -834,8 +860,8 @@ private:
QString callsignSelected(); QString callsignSelected();
bool isRecentOffset(int offset); bool isRecentOffset(int offset);
void markOffsetRecent(int offset); void markOffsetRecent(int offset);
bool isDirectedOffset(int offset); bool isDirectedOffset(int offset, bool *pIsAllCall);
void markOffsetDirected(int offset); void markOffsetDirected(int offset, bool isAllCall);
void processActivity(bool force=false); void processActivity(bool force=false);
void processRxActivity(); void processRxActivity();
void processCompoundActivity(); void processCompoundActivity();
+68 -5
View File
@@ -221,7 +221,7 @@ QPushButton[oob=&quot;true&quot;] {
</string> </string>
</property> </property>
<property name="text"> <property name="text">
<string>14.074 000</string> <string>14.078 000</string>
</property> </property>
<property name="flat"> <property name="flat">
<bool>true</bool> <bool>true</bool>
@@ -508,6 +508,9 @@ color : white;
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable or disable the receiver&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QPushButton { <string notr="true">QPushButton {
font-family: helvetica; font-family: helvetica;
@@ -640,6 +643,9 @@ background-color: yellow;
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Transmit a tuning tone&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QPushButton { <string notr="true">QPushButton {
font-family: helvetica; font-family: helvetica;
@@ -701,6 +707,9 @@ background-color: yellow;
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable or disable automatic station replies to directed queries&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QPushButton { <string notr="true">QPushButton {
font-family: helvetica; font-family: helvetica;
@@ -761,6 +770,9 @@ background-color: #6699ff;
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable or disable spotting of callsigns heard to PSKReporter&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QPushButton { <string notr="true">QPushButton {
font-family: helvetica; font-family: helvetica;
@@ -821,6 +833,9 @@ background-color: #00ff00;
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Enable or disable the automatic beacon&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QPushButton { <string notr="true">QPushButton {
font-family: helvetica; font-family: helvetica;
@@ -881,6 +896,9 @@ background-color: #6699ff;
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Insert a new entry into the log&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QPushButton { <string notr="true">QPushButton {
font-family: helvetica; font-family: helvetica;
@@ -951,6 +969,9 @@ background-color: #00ff00;
<pointsize>12</pointsize> <pointsize>12</pointsize>
</font> </font>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Received band activity is displayed with time since last heard, SNR, and the text received for each frequency offset in the passband.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="sizeAdjustPolicy"> <property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum> <enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
</property> </property>
@@ -1107,6 +1128,9 @@ QTextEdit[transmitting=&quot;true&quot;] {
<pointsize>12</pointsize> <pointsize>12</pointsize>
</font> </font>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Received callsigns are displayed with time since last heard, SNR, and grid locator (if reported).&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="autoScroll"> <property name="autoScroll">
<bool>false</bool> <bool>false</bool>
</property> </property>
@@ -1154,6 +1178,11 @@ QTextEdit[transmitting=&quot;true&quot;] {
<string>Callsign</string> <string>Callsign</string>
</property> </property>
</column> </column>
<column>
<property name="text">
<string>Offset</string>
</property>
</column>
<column> <column>
<property name="text"> <property name="text">
<string>Age</string> <string>Age</string>
@@ -1232,6 +1261,12 @@ QTextEdit[transmitting=&quot;true&quot;] {
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="visible">
<bool>false</bool>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Send your station location message&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>QTH</string> <string>QTH</string>
</property> </property>
@@ -1245,6 +1280,9 @@ QTextEdit[transmitting=&quot;true&quot;] {
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Send a CQ message&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>CQ</string> <string>CQ</string>
</property> </property>
@@ -1261,24 +1299,27 @@ QTextEdit[transmitting=&quot;true&quot;] {
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Stop transmitting&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Halt</string> <string>Halt</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="2"> <item row="1" column="2">
<widget class="QPushButton" name="qtcMacroButton"> <widget class="QPushButton" name="replyMacroButton">
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>0</width> <width>0</width>
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="visible"> <property name="toolTip">
<bool>true</bool> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Reply to a CQ&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>QTC</string> <string>Reply</string>
</property> </property>
</widget> </widget>
</item> </item>
@@ -1290,6 +1331,9 @@ QTextEdit[transmitting=&quot;true&quot;] {
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Send a macro&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Macros</string> <string>Macros</string>
</property> </property>
@@ -1306,6 +1350,9 @@ QTextEdit[transmitting=&quot;true&quot;] {
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Start transmitting&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QPushButton:checked { <string notr="true">QPushButton:checked {
background-color: #00ff00; background-color: #00ff00;
@@ -1330,6 +1377,9 @@ background:yellow;
<height>30</height> <height>30</height>
</size> </size>
</property> </property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Send a directed message to another station&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text"> <property name="text">
<string>Directed</string> <string>Directed</string>
</property> </property>
@@ -4308,6 +4358,9 @@ list. The list can be maintained in Settings (F2).</string>
<property name="title"> <property name="title">
<string>Window</string> <string>Window</string>
</property> </property>
<addaction name="actionSort_Band_Activity"/>
<addaction name="actionSort_Call_Activity"/>
<addaction name="separator"/>
<addaction name="actionShow_Band_Activity"/> <addaction name="actionShow_Band_Activity"/>
<addaction name="actionShow_Call_Activity"/> <addaction name="actionShow_Call_Activity"/>
<addaction name="actionShow_Waterfall"/> <addaction name="actionShow_Waterfall"/>
@@ -5003,6 +5056,16 @@ list. The list can be maintained in Settings (F2).</string>
<string>Reset Window Sizes</string> <string>Reset Window Sizes</string>
</property> </property>
</action> </action>
<action name="actionSort_Band_Activity">
<property name="text">
<string>Sort Band Activity...</string>
</property>
</action>
<action name="actionSort_Call_Activity">
<property name="text">
<string>Sort Call Activity...</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<customwidgets> <customwidgets>
+77 -5
View File
@@ -50,6 +50,8 @@ CPlotter::CPlotter(QWidget *parent) : //CPlotter Constructor
setAttribute(Qt::WA_NoSystemBackground, true); setAttribute(Qt::WA_NoSystemBackground, true);
m_bReplot=false; m_bReplot=false;
setMouseTracking(true);
// contextual pop up menu // contextual pop up menu
setContextMenuPolicy (Qt::CustomContextMenu); setContextMenuPolicy (Qt::CustomContextMenu);
connect (this, &QWidget::customContextMenuRequested, [this] (QPoint const& pos) { connect (this, &QWidget::customContextMenuRequested, [this] (QPoint const& pos) {
@@ -91,8 +93,10 @@ void CPlotter::resizeEvent(QResizeEvent* ) //resizeEvent()
m_h1=m_h-m_h2; m_h1=m_h-m_h2;
// m_line=0; // m_line=0;
m_FullOverlayPixmap = QPixmap(m_Size.width(), m_h); m_DialOverlayPixmap = QPixmap(m_Size.width(), m_h);
m_FullOverlayPixmap.fill(Qt::transparent); m_DialOverlayPixmap.fill(Qt::transparent);
m_HoverOverlayPixmap = QPixmap(m_Size.width(), m_h);
m_HoverOverlayPixmap.fill(Qt::transparent);
m_2DPixmap = QPixmap(m_Size.width(), m_h2); m_2DPixmap = QPixmap(m_Size.width(), m_h2);
m_2DPixmap.fill(Qt::black); m_2DPixmap.fill(Qt::black);
m_WaterfallPixmap = QPixmap(m_Size.width(), m_h1); m_WaterfallPixmap = QPixmap(m_Size.width(), m_h1);
@@ -117,7 +121,12 @@ void CPlotter::paintEvent(QPaintEvent *) // paint
painter.drawPixmap(0,m_h1,m_2DPixmap); painter.drawPixmap(0,m_h1,m_2DPixmap);
int x = XfromFreq(m_rxFreq); int x = XfromFreq(m_rxFreq);
painter.drawPixmap(x,0,m_FullOverlayPixmap); painter.drawPixmap(x,0,m_DialOverlayPixmap);
if(m_lastMouseX >= 0 && m_lastMouseX != x){
painter.drawPixmap(m_lastMouseX, 0, m_HoverOverlayPixmap);
}
m_paintEventBusy=false; m_paintEventBusy=false;
} }
@@ -329,6 +338,7 @@ void CPlotter::DrawOverlay() //DrawOverlay()
QPen penOrange(QColor(255,165,0),3); QPen penOrange(QColor(255,165,0),3);
QPen penGreen(Qt::green, 3); //Mark Tol range with green line QPen penGreen(Qt::green, 3); //Mark Tol range with green line
QPen penRed(Qt::red, 3); //Mark Tx freq with red QPen penRed(Qt::red, 3); //Mark Tx freq with red
QPen penYellow(QColor(243, 156, 18), 3); //Mark band block freq with this pen
QPainter painter(&m_OverlayPixmap); QPainter painter(&m_OverlayPixmap);
painter.initFrom(this); painter.initFrom(this);
QLinearGradient gradient(0, 0, 0 ,m_h2); //fill background with gradient QLinearGradient gradient(0, 0, 0 ,m_h2); //fill background with gradient
@@ -396,7 +406,7 @@ void CPlotter::DrawOverlay() //DrawOverlay()
if(m_freqPerDiv==200) minor=4; if(m_freqPerDiv==200) minor=4;
for( int i=1; i<minor*m_hdivs; i++) { //minor ticks for( int i=1; i<minor*m_hdivs; i++) { //minor ticks
x = i*pixperdiv/minor; x = i*pixperdiv/minor;
painter0.drawLine(x,24,x,30); painter0.drawLine(x,22,x,30);
} }
//draw frequency values //draw frequency values
@@ -557,9 +567,17 @@ void CPlotter::DrawOverlay() //DrawOverlay()
} }
} }
x1=XfromFreq(0);
x2=XfromFreq(500);
if(x1<=m_w and x2>0) {
painter0.setPen(penYellow); //Mark bottom of sub-band
painter0.drawLine(x1+1,26,x2-2,26);
painter0.drawLine(x1+1,28,x2-2,28);
}
if(m_mode=="FT8"){ if(m_mode=="FT8"){
int fwidth=XfromFreq(m_rxFreq+bw)-XfromFreq(m_rxFreq); int fwidth=XfromFreq(m_rxFreq+bw)-XfromFreq(m_rxFreq);
QPainter overPainter(&m_FullOverlayPixmap); QPainter overPainter(&m_DialOverlayPixmap);
overPainter.initFrom(this); overPainter.initFrom(this);
overPainter.setCompositionMode(QPainter::CompositionMode_Source); overPainter.setCompositionMode(QPainter::CompositionMode_Source);
overPainter.fillRect(0, 0, m_Size.width(), m_h, Qt::transparent); overPainter.fillRect(0, 0, m_Size.width(), m_h, Qt::transparent);
@@ -571,6 +589,20 @@ void CPlotter::DrawOverlay() //DrawOverlay()
overPainter.setPen(penRed); overPainter.setPen(penRed);
overPainter.drawLine(0, 26, fwidth, 26); overPainter.drawLine(0, 26, fwidth, 26);
overPainter.drawLine(0, 28, fwidth, 28); overPainter.drawLine(0, 28, fwidth, 28);
QPainter hoverPainter(&m_HoverOverlayPixmap);
hoverPainter.initFrom(this);
hoverPainter.setCompositionMode(QPainter::CompositionMode_Source);
hoverPainter.fillRect(0, 0, m_Size.width(), m_h, Qt::transparent);
hoverPainter.setPen(QPen(Qt::white));
hoverPainter.drawLine(0, 30, 0, m_h);
hoverPainter.drawLine(fwidth+1, 30, fwidth+1, m_h);
#if DRAW_FREQ_OVERLAY
int f = FreqfromX(m_lastMouseX);
hoverPainter.setFont(Font);
hoverPainter.drawText(fwidth + 5, m_h, QString("%1").arg(f));
#endif
} }
} }
@@ -692,6 +724,46 @@ void CPlotter::setRxFreq (int x) //setRxFreq
int CPlotter::rxFreq() {return m_rxFreq;} //rxFreq int CPlotter::rxFreq() {return m_rxFreq;} //rxFreq
void CPlotter::leaveEvent(QEvent *event)
{
m_lastMouseX = -1;
}
void CPlotter::wheelEvent(QWheelEvent *event){
auto delta = event->angleDelta();
if(delta.isNull()){
event->ignore();
return;
}
int newFreq = rxFreq();
int dir = delta.y() > 0 ? 1 : -1;
bool ctrl = (event->modifiers() & Qt::ControlModifier);
if(ctrl){
newFreq += dir;
} else {
newFreq = newFreq/10*10 + dir*10;
}
emit setFreq1 (newFreq, newFreq);
}
void CPlotter::mouseMoveEvent (QMouseEvent * event)
{
int x = event->x();
if(x < 0) x = 0;
if(x>m_Size.width()) x = m_Size.width();
m_lastMouseX = x;
#if DRAW_FREQ_OVERLAY
DrawOverlay();
#endif
update();
event->ignore();
}
void CPlotter::mouseReleaseEvent (QMouseEvent * event) void CPlotter::mouseReleaseEvent (QMouseEvent * event)
{ {
if (Qt::LeftButton == event->button ()) { if (Qt::LeftButton == event->button ()) {
+6 -1
View File
@@ -95,6 +95,9 @@ protected:
//re-implemented widget event handlers //re-implemented widget event handlers
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;
void resizeEvent(QResizeEvent* event) override; void resizeEvent(QResizeEvent* event) override;
void leaveEvent(QEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void mouseMoveEvent(QMouseEvent * event) override;
void mouseReleaseEvent (QMouseEvent * event) override; void mouseReleaseEvent (QMouseEvent * event) override;
void mouseDoubleClickEvent (QMouseEvent * event) override; void mouseDoubleClickEvent (QMouseEvent * event) override;
@@ -128,7 +131,8 @@ private:
qint32 m_ia; qint32 m_ia;
qint32 m_ib; qint32 m_ib;
QPixmap m_FullOverlayPixmap; QPixmap m_DialOverlayPixmap;
QPixmap m_HoverOverlayPixmap;
QPixmap m_WaterfallPixmap; QPixmap m_WaterfallPixmap;
QPixmap m_2DPixmap; QPixmap m_2DPixmap;
QPixmap m_ScalePixmap; QPixmap m_ScalePixmap;
@@ -174,6 +178,7 @@ private:
qint32 m_startFreq; qint32 m_startFreq;
qint32 m_tol; qint32 m_tol;
qint32 m_j; qint32 m_j;
qint32 m_lastMouseX;
char m_sutc[6]; char m_sutc[6];
}; };
+39 -12
View File
@@ -30,7 +30,7 @@
const int nalphabet = 41; const int nalphabet = 41;
QString alphabet = {"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?"}; // alphabet to encode _into_ for FT8 freetext transmission QString alphabet = {"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?"}; // alphabet to encode _into_ for FT8 freetext transmission
QString alphabet72 = {"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-+/?."}; QString alphabet72 = {"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-+/?."};
QString grid_pattern = {R"((?<grid>[A-R]{2}[0-9]{2})+)"}; QString grid_pattern = {R"((?<grid>[A-X]{2}[0-9]{2}(?:[A-X]{2}(?:[0-9]{2})?)*)+)"};
QString orig_compound_callsign_pattern = {R"((?<callsign>(\d|[A-Z])+\/?((\d|[A-Z]){2,})(\/(\d|[A-Z])+)?(\/(\d|[A-Z])+)?))"}; QString orig_compound_callsign_pattern = {R"((?<callsign>(\d|[A-Z])+\/?((\d|[A-Z]){2,})(\/(\d|[A-Z])+)?(\/(\d|[A-Z])+)?))"};
QString compound_callsign_pattern = {R"((?<callsign>\b(?<prefix>[A-Z0-9]{1,4}\/)?(?<base>([0-9A-Z])?([0-9A-Z])([0-9])([A-Z])?([A-Z])?([A-Z])?)(?<suffix>\/[A-Z0-9]{1,4})?)\b)"}; QString compound_callsign_pattern = {R"((?<callsign>\b(?<prefix>[A-Z0-9]{1,4}\/)?(?<base>([0-9A-Z])?([0-9A-Z])([0-9])([A-Z])?([A-Z])?([A-Z])?)(?<suffix>\/[A-Z0-9]{1,4})?)\b)"};
QString pack_callsign_pattern = {R"(([0-9A-Z ])([0-9A-Z])([0-9])([A-Z ])([A-Z ])([A-Z ]))"}; QString pack_callsign_pattern = {R"(([0-9A-Z ])([0-9A-Z])([0-9])([A-Z ])([A-Z ])([A-Z ]))"};
@@ -44,18 +44,28 @@ QMap<QString, int> directed_cmds = {
{"@", 1 }, // query qth {"@", 1 }, // query qth
{"&", 2 }, // query station message {"&", 2 }, // query station message
{"$", 3 }, // query station(s) heard {"$", 3 }, // query station(s) heard
{"^", 4 }, // query grid
{"%", 5 }, // query pwr {"%", 5 }, // query pwr
// 4.
{"|", 6 }, // retransmit message {"|", 6 }, // retransmit message
{"!", 7 }, // alert message {"!", 7 }, // alert message
{"#", 8 }, // all or nothing message {"#", 8 }, // all or nothing message
// {"=", 9 }, // unused? (can we even use equals?) // {"=", 9 }, // unused
// {"/", 10 }, // unused? (can we even use stroke?) // {"/", 10 }, // unused
// {"/", 11 }, // unused
// {"/", 12 }, // unused
// {"/", 13 }, // unused
// directed responses // directed responses
{" QSO", 13 }, // can you communicate with? i can communicate with
{" APRS:", 14 }, // send an aprs packet
{" GRID", 15 }, // this is my current grid locator
{" QTC", 16 }, // this is my qtc message
{" QTH", 17 }, // this is my qth message
{" FB", 18 }, // fine business
{" HW CPY?", 19 }, // how do you copy?
{" HEARING", 20 }, // i am hearing the following stations {" HEARING", 20 }, // i am hearing the following stations
{" RR", 21 }, // roger roger (not visible in UI but still exists) {" RR", 21 }, // roger roger
{" QSL?", 22 }, // do you copy? {" QSL?", 22 }, // do you copy?
{" QSL", 23 }, // i copy {" QSL", 23 }, // i copy
{" PWR", 24 }, // power level {" PWR", 24 }, // power level
@@ -68,12 +78,21 @@ QMap<QString, int> directed_cmds = {
{" ", 31 }, // send freetext {" ", 31 }, // send freetext
}; };
QSet<int> allowed_cmds = {0, 1, 2, 3, /*4,*/ 5, 6, 7, 8, /*...*/ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; QSet<int> allowed_cmds = {0, 1, 2, 3, 4, 5, 6, 7, 8, /*...*/ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
QSet<int> buffered_cmds = {6, 7, 8}; QSet<int> buffered_cmds = {6, 7, 8, 13, 14, 15};
QMap<int, int> checksum_cmds = {
{ 6, 16 },
{ 7, 16 },
{ 8, 32 },
{ 13, 16 },
{ 14, 16 },
{ 15, 0 }
};
QString callsign_pattern = QString("(?<callsign>[A-Z0-9/]+)"); QString callsign_pattern = QString("(?<callsign>[A-Z0-9/]+)");
QString optional_cmd_pattern = QString("(?<cmd>\\s?(?:AGN[?]|ACK|73|YES|NO|SNR|PWR|QSL[?]?|RR|HEARING|[?@&$%|!# ]))?"); QString optional_cmd_pattern = QString("(?<cmd>\\s?(?:AGN[?]|ACK|73|YES|NO|SNR|PWR|QSL[?]?|RR|HEARING|HW CPY[?]|FB|QTH|QTC|GRID|APRS[:]|QSO|[?@&$%|!#^ ]))?");
QString optional_grid_pattern = QString("(?<grid>\\s?[A-R]{2}[0-9]{2})?"); QString optional_grid_pattern = QString("(?<grid>\\s?[A-R]{2}[0-9]{2})?");
QString optional_extended_grid_pattern = QString("^(?<grid>\\s?(?:[A-R]{2}[0-9]{2}(?:[A-X]{2}(?:[0-9]{2})?)*))?"); QString optional_extended_grid_pattern = QString("^(?<grid>\\s?(?:[A-R]{2}[0-9]{2}(?:[A-X]{2}(?:[0-9]{2})?)*))?");
QString optional_pwr_pattern = QString("(?<pwr>(?<=PWR)\\s?\\d+\\s?[KM]?W)?"); QString optional_pwr_pattern = QString("(?<pwr>(?<=PWR)\\s?\\d+\\s?[KM]?W)?");
@@ -947,7 +966,7 @@ QString Varicode::unpackCallsign(quint32 value){
return callsign; return callsign;
} }
QString deg2grid(float dlong, float dlat){ QString Varicode::deg2grid(float dlong, float dlat){
QChar grid[6]; QChar grid[6];
if(dlong < -180){ if(dlong < -180){
@@ -980,7 +999,7 @@ QString deg2grid(float dlong, float dlat){
return QString(grid, 6); return QString(grid, 6);
} }
QPair<float, float> grid2deg(QString const &grid){ QPair<float, float> Varicode::grid2deg(QString const &grid){
QPair<float, float> longLat; QPair<float, float> longLat;
QString g = grid; QString g = grid;
@@ -1012,7 +1031,7 @@ quint16 Varicode::packGrid(QString const& value){
return (1<<15)-1; return (1<<15)-1;
} }
auto pair = grid2deg(grid.left(4)); auto pair = Varicode::grid2deg(grid.left(4));
int ilong = pair.first; int ilong = pair.first;
int ilat = pair.second + 90; int ilat = pair.second + 90;
@@ -1027,7 +1046,7 @@ QString Varicode::unpackGrid(quint16 value){
float dlat = value % 180 - 90; float dlat = value % 180 - 90;
float dlong = value / 180 * 2 - 180 + 2; float dlong = value / 180 * 2 - 180 + 2;
return deg2grid(dlong, dlat).left(4); return Varicode::deg2grid(dlong, dlat).left(4);
} }
// pack a number or snr into an integer between 0 & 62 // pack a number or snr into an integer between 0 & 62
@@ -1115,6 +1134,14 @@ bool Varicode::isCommandBuffered(const QString &cmd){
return directed_cmds.contains(cmd) && buffered_cmds.contains(directed_cmds[cmd]); return directed_cmds.contains(cmd) && buffered_cmds.contains(directed_cmds[cmd]);
} }
int Varicode::isCommandChecksumed(const QString &cmd){
if(!directed_cmds.contains(cmd) || !checksum_cmds.contains(directed_cmds[cmd])){
return 0;
}
return checksum_cmds[directed_cmds[cmd]];
}
// CQCQCQ EM73 // CQCQCQ EM73
// BEACON EM73 // BEACON EM73
QString Varicode::packBeaconMessage(QString const &text, const QString &callsign, int *n){ QString Varicode::packBeaconMessage(QString const &text, const QString &callsign, int *n){
+6 -3
View File
@@ -41,11 +41,11 @@ public:
"FrameBeacon", "FrameBeacon",
"FrameCompound", "FrameCompound",
"FrameCompoundDirected", "FrameCompoundDirected",
"FrameDirectedPositive", "FrameDirected",
"FrameDirectedNegative", "FrameReservedA",
"FrameDataUnpadded", "FrameDataUnpadded",
"FrameDataPadded", "FrameDataPadded",
"FrameReserved" "FrameReservedB"
}; };
if(type > FrameTypeMax){ if(type > FrameTypeMax){
@@ -109,6 +109,8 @@ public:
static quint32 packCallsign(QString const& value); static quint32 packCallsign(QString const& value);
static QString unpackCallsign(quint32 value); static QString unpackCallsign(quint32 value);
static QString deg2grid(float dlong, float dlat);
static QPair<float, float> grid2deg(QString const &grid);
static quint16 packGrid(QString const& value); static quint16 packGrid(QString const& value);
static QString unpackGrid(quint16 value); static QString unpackGrid(quint16 value);
@@ -119,6 +121,7 @@ public:
static bool isCommandAllowed(const QString &cmd); static bool isCommandAllowed(const QString &cmd);
static bool isCommandBuffered(const QString &cmd); static bool isCommandBuffered(const QString &cmd);
static int isCommandChecksumed(const QString &cmd);
static QString packBeaconMessage(QString const &text, QString const&callsign, int *n); static QString packBeaconMessage(QString const &text, QString const&callsign, int *n);
static QStringList unpackBeaconMessage(const QString &text, quint8 *pType, bool *isAlt); static QStringList unpackBeaconMessage(const QString &text, quint8 *pType, bool *isAlt);
+5 -3
View File
@@ -80,14 +80,14 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) :
ui->widePlot->setBinsPerPixel(nbpp); ui->widePlot->setBinsPerPixel(nbpp);
ui->sbPercent2dPlot->setValue(m_Percent2DScreen); ui->sbPercent2dPlot->setValue(m_Percent2DScreen);
ui->widePlot->SetPercent2DScreen(m_Percent2DScreen); ui->widePlot->SetPercent2DScreen(m_Percent2DScreen);
ui->widePlot->setStartFreq(m_settings->value("StartFreq",0).toInt()); ui->widePlot->setStartFreq(m_settings->value("StartFreq", 500).toInt());
ui->fStartSpinBox->setValue(ui->widePlot->startFreq()); ui->fStartSpinBox->setValue(ui->widePlot->startFreq());
m_waterfallPalette=m_settings->value("WaterfallPalette","Default").toString(); m_waterfallPalette=m_settings->value("WaterfallPalette","Default").toString();
m_userPalette = WFPalette {m_settings->value("UserPalette").value<WFPalette::Colours> ()}; m_userPalette = WFPalette {m_settings->value("UserPalette").value<WFPalette::Colours> ()};
m_fMinPerBand = m_settings->value ("FminPerBand").toHash (); m_fMinPerBand = m_settings->value ("FminPerBand").toHash ();
setRxRange (); setRxRange ();
ui->controls_widget->setVisible(!m_settings->value("HideControls", true).toBool()); ui->controls_widget->setVisible(!m_settings->value("HideControls", false).toBool());
ui->cbControls->setChecked(!m_settings->value("HideControls", true).toBool()); ui->cbControls->setChecked(!m_settings->value("HideControls", false).toBool());
} }
int index=0; int index=0;
@@ -212,6 +212,8 @@ void WideGraph::on_offsetSpinBox_valueChanged(int n){
return; return;
} }
n = qMax(500, n);
setRxFreq(n); setRxFreq(n);
setTxFreq(n); setTxFreq(n);
setFreq2(n, n); setFreq2(n, n);
+3
View File
@@ -177,6 +177,9 @@
<property name="singleStep"> <property name="singleStep">
<number>100</number> <number>100</number>
</property> </property>
<property name="value">
<number>500</number>
</property>
</widget> </widget>
</item> </item>
<item row="1" column="12"> <item row="1" column="12">
+6 -2
View File
@@ -70,7 +70,9 @@ SOURCES += \
EqualizationToolsDialog.cpp \ EqualizationToolsDialog.cpp \
varicode.cpp \ varicode.cpp \
NetworkMessage.cpp \ NetworkMessage.cpp \
MessageClient.cpp MessageClient.cpp \
SelfDestructMessageBox.cpp \
APRSISClient.cpp
HEADERS += qt_helpers.hpp \ HEADERS += qt_helpers.hpp \
pimpl_h.hpp pimpl_impl.hpp \ pimpl_h.hpp pimpl_impl.hpp \
@@ -92,7 +94,9 @@ HEADERS += qt_helpers.hpp \
qpriorityqueue.h \ qpriorityqueue.h \
crc.h \ crc.h \
NetworkMessage.hpp \ NetworkMessage.hpp \
MessageClient.hpp MessageClient.hpp \
SelfDestructMessageBox.h \
APRSISClient.h
INCLUDEPATH += qmake_only INCLUDEPATH += qmake_only