Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 95a91fb526 | |||
| 081bc0380b | |||
| 77715347c7 | |||
| 712580d08c | |||
| 084765f271 | |||
| d2b7229815 | |||
| 63739b9d31 | |||
| d1b239201c | |||
| f06df77db2 | |||
| 2250589f83 | |||
| 65a19e4707 | |||
| c8c4f98610 | |||
| 0ecbbd0da1 | |||
| b5cebe41e8 | |||
| 83b05df312 | |||
| 541bd8bca3 | |||
| 565bdb5690 | |||
| 7868c3fe70 | |||
| adcc728492 | |||
| 2fa1fcd4f8 | |||
| 8eb0fc327d | |||
| e6f83e999b | |||
| b10ccc370f | |||
| 121ffb48f6 | |||
| 4698db27f6 | |||
| fe1463b730 | |||
| ad154cb2e6 | |||
| 5166b1e0dd | |||
| 5d0e91a5ed | |||
| c01238f5e0 | |||
| 726484a05a | |||
| b7d2a370f8 | |||
| 6c8902d802 | |||
| 1002dcbc1b | |||
| f2ca9caec7 | |||
| 96ca7786e5 | |||
| eecde27cd8 | |||
| d4bb4cf49a | |||
| db74c22890 | |||
| 69b90b243a | |||
| 9bac05c86c | |||
| fde19eebd8 | |||
| 6b4390fe5c | |||
| ad4e567392 | |||
| 612df625ed | |||
| 9475ea7461 | |||
| 5fad5497d2 | |||
| 9815c4dde9 | |||
| 60c0f24ef8 | |||
| e74e20680a | |||
| ee44e2e5d7 | |||
| 43574b10b1 | |||
| 08f046c289 | |||
| 5f4a66e916 | |||
| bc97c96a5b | |||
| 3b1519c603 | |||
| f30c2e3858 | |||
| c60efba4ca | |||
| 5694b96f55 |
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -304,6 +304,8 @@ set (wsjtx_CXXSRCS
|
||||
messageaveraging.cpp
|
||||
WsprTxScheduler.cpp
|
||||
varicode.cpp
|
||||
SelfDestructMessageBox.cpp
|
||||
APRSISClient.cpp
|
||||
mainwindow.cpp
|
||||
Configuration.cpp
|
||||
main.cpp
|
||||
|
||||
+92
-40
@@ -196,11 +196,14 @@ namespace
|
||||
int const combo_box_item_disabled (0);
|
||||
|
||||
// QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"};
|
||||
QRegExp message_alphabet {"[- @A-Za-z0-9+./?#<>]*"};
|
||||
QRegExp message_alphabet {"[^\\x00-\\x1F]*"};
|
||||
|
||||
// Magic numbers for file validation
|
||||
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_station_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 delete_macro ();
|
||||
void delete_selected_macros (QModelIndexList);
|
||||
@@ -553,14 +557,15 @@ private:
|
||||
QString my_station_;
|
||||
int my_dBm_;
|
||||
QString my_qth_;
|
||||
QString reply_;
|
||||
int callsign_aging_;
|
||||
int activity_aging_;
|
||||
QColor color_CQ_;
|
||||
QColor next_color_CQ_;
|
||||
QColor color_MyCall_;
|
||||
QColor next_color_MyCall_;
|
||||
QColor color_TxMsg_;
|
||||
QColor next_color_TxMsg_;
|
||||
QColor color_ReceivedMsg_;
|
||||
QColor next_color_ReceivedMsg_;
|
||||
QColor color_DXCC_;
|
||||
QColor next_color_DXCC_;
|
||||
QColor color_NewCall_;
|
||||
@@ -573,11 +578,12 @@ private:
|
||||
double txDelay_;
|
||||
bool id_after_73_;
|
||||
bool tx_QSY_allowed_;
|
||||
bool spot_to_psk_reporter_;
|
||||
bool spot_to_reporting_networks_;
|
||||
bool transmit_directed_;
|
||||
bool autoreply_off_at_startup_;
|
||||
bool monitor_off_at_startup_;
|
||||
bool monitor_last_used_;
|
||||
bool log_as_RTTY_;
|
||||
bool log_as_DATA_;
|
||||
bool report_in_comments_;
|
||||
bool prompt_to_log_;
|
||||
bool insert_blank_;
|
||||
@@ -612,6 +618,7 @@ private:
|
||||
bool accept_udp_requests_;
|
||||
bool udpWindowToFront_;
|
||||
bool udpWindowRestore_;
|
||||
bool udpEnabled_;
|
||||
DataMode data_mode_;
|
||||
bool pwrBandTxMemory_;
|
||||
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_;}
|
||||
QColor Configuration::color_CQ () const {return m_->color_CQ_;}
|
||||
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_NewCall () const {return m_->color_NewCall_;}
|
||||
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_;}
|
||||
bool Configuration::id_after_73 () const {return m_->id_after_73_;}
|
||||
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
|
||||
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){
|
||||
m_->spot_to_psk_reporter_ = spot;
|
||||
if(m_->spot_to_reporting_networks_ != spot){
|
||||
m_->spot_to_reporting_networks_ = spot;
|
||||
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::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::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::prompt_to_log () const {return m_->prompt_to_log_;}
|
||||
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::udpWindowToFront () const {return m_->udpWindowToFront_;}
|
||||
bool Configuration::udpWindowRestore () const {return m_->udpWindowRestore_;}
|
||||
bool Configuration::udpEnabled () const {return m_->udpEnabled_;}
|
||||
Bands * Configuration::bands () {return &m_->bands_;}
|
||||
Bands const * Configuration::bands () const {return &m_->bands_;}
|
||||
StationList * Configuration::stations () {return &m_->stations_;}
|
||||
@@ -865,6 +874,11 @@ QString Configuration::my_qth() const
|
||||
return m_->my_qth_;
|
||||
}
|
||||
|
||||
QString Configuration::reply() const
|
||||
{
|
||||
return m_->reply_;
|
||||
}
|
||||
|
||||
int Configuration::callsign_aging() const
|
||||
{
|
||||
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"};
|
||||
}
|
||||
|
||||
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
|
||||
QDir dest_dir {default_save_directory_};
|
||||
dest_dir.cd (samples_dir);
|
||||
@@ -1012,10 +1035,11 @@ Configuration::impl::impl (Configuration * self, QDir const& temp_directory,
|
||||
// validation
|
||||
//
|
||||
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_->station_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->setMaximum (std::numeric_limits<port_type>::max ());
|
||||
@@ -1235,15 +1259,16 @@ void Configuration::impl::initialize_models ()
|
||||
ui_->grid_line_edit->setPalette (pal);
|
||||
ui_->auto_switch_bands_check_box->setChecked(auto_switch_bands_);
|
||||
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_->activity_aging_spin_box->setValue(activity_aging_);
|
||||
ui_->station_message_line_edit->setText (my_station_.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_->labCQ->setStyleSheet(QString("background: %1").arg(color_CQ_.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_->labNewCall->setStyleSheet(QString("background: %1").arg(color_NewCall_.name()));
|
||||
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_->CW_id_after_73_check_box->setChecked (id_after_73_);
|
||||
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_->monitor_off_check_box->setChecked (monitor_off_at_startup_);
|
||||
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_->report_in_comments_check_box->setChecked (report_in_comments_);
|
||||
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_->enable_n1mm_broadcast_check_box->setChecked (broadcast_to_n1mm_);
|
||||
ui_->udpWindowToFront->setChecked(udpWindowToFront_);
|
||||
ui_->udpEnable->setChecked(udpEnabled_);
|
||||
ui_->udpWindowRestore->setChecked(udpWindowRestore_);
|
||||
ui_->calibration_intercept_spin_box->setValue (calibration_.intercept);
|
||||
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 ();
|
||||
activity_aging_ = settings_->value ("ActivityAging", 2).toInt ();
|
||||
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_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_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> ();
|
||||
|
||||
transmit_directed_ = settings_->value ("TransmitDirected", true).toBool();
|
||||
autoreply_off_at_startup_ = settings_->value ("AutoreplyOFF", false).toBool ();
|
||||
monitor_off_at_startup_ = settings_->value ("MonitorOFF", 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 ();
|
||||
tx_QSY_allowed_ = settings_->value ("TxQSYAllowed", 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> ();
|
||||
|
||||
if (settings_->contains ("FrequenciesForRegionModes"))
|
||||
if (settings_->contains (versionedFrequenciesSettingsKey))
|
||||
{
|
||||
auto const& v = settings_->value ("FrequenciesForRegionModes");
|
||||
auto const& v = settings_->value (versionedFrequenciesSettingsKey);
|
||||
if (v.isValid ())
|
||||
{
|
||||
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> ());
|
||||
|
||||
log_as_RTTY_ = settings_->value ("toRTTY", false).toBool ();
|
||||
log_as_DATA_ = settings_->value ("toRTTY", false).toBool ();
|
||||
report_in_comments_ = settings_->value("dBtoComments", false).toBool ();
|
||||
rig_params_.rig_name = settings_->value ("Rig", TransceiverFactory::basic_transceiver_name_).toString ();
|
||||
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 ();
|
||||
quick_call_ = settings_->value ("QuickCall", 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 ();
|
||||
TX_messages_ = settings_->value ("Tx2QSO", true).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 ();
|
||||
broadcast_to_n1mm_ = settings_->value ("BroadcastToN1MM", false).toBool ();
|
||||
accept_udp_requests_ = settings_->value ("AcceptUDPRequests", false).toBool ();
|
||||
udpEnabled_ = settings_->value("UDPEnabled", false).toBool();
|
||||
udpWindowToFront_ = settings_->value ("udpWindowToFront",false).toBool ();
|
||||
udpWindowRestore_ = settings_->value ("udpWindowRestore",false).toBool ();
|
||||
calibration_.intercept = settings_->value ("CalibrationIntercept", 0.).toDouble ();
|
||||
@@ -1558,11 +1588,12 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("MyStation", my_station_);
|
||||
settings_->setValue ("MyPower", my_dBm_);
|
||||
settings_->setValue ("MyQTH", my_qth_);
|
||||
settings_->setValue ("Reply", reply_);
|
||||
settings_->setValue ("CallsignAging", callsign_aging_);
|
||||
settings_->setValue ("ActivityAging", activity_aging_);
|
||||
settings_->setValue("colorCQ",color_CQ_);
|
||||
settings_->setValue("colorMyCall",color_MyCall_);
|
||||
settings_->setValue("colorTxMsg",color_TxMsg_);
|
||||
settings_->setValue("colorReceivedMsg",color_ReceivedMsg_);
|
||||
settings_->setValue("colorDXCC",color_DXCC_);
|
||||
settings_->setValue("colorNewCall",color_NewCall_);
|
||||
settings_->setValue ("Font", font_.toString ());
|
||||
@@ -1598,16 +1629,17 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("AudioInputChannel", AudioDevice::toString (audio_input_channel_));
|
||||
settings_->setValue ("AudioOutputChannel", AudioDevice::toString (audio_output_channel_));
|
||||
settings_->setValue ("Type2MsgGen", QVariant::fromValue (type_2_msg_gen_));
|
||||
settings_->setValue ("TransmitDirected", transmit_directed_);
|
||||
settings_->setValue ("AutoreplyOFF", autoreply_off_at_startup_);
|
||||
settings_->setValue ("MonitorOFF", monitor_off_at_startup_);
|
||||
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 ("TxQSYAllowed", tx_QSY_allowed_);
|
||||
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 ("toRTTY", log_as_RTTY_);
|
||||
settings_->setValue ("toRTTY", log_as_DATA_);
|
||||
settings_->setValue ("dBtoComments", report_in_comments_);
|
||||
settings_->setValue ("Rig", rig_params_.rig_name);
|
||||
settings_->setValue ("CATNetworkPort", rig_params_.network_port);
|
||||
@@ -1651,6 +1683,7 @@ void Configuration::impl::write_settings ()
|
||||
settings_->setValue ("N1MMServerPort", n1mm_server_port_);
|
||||
settings_->setValue ("BroadcastToN1MM", broadcast_to_n1mm_);
|
||||
settings_->setValue ("AcceptUDPRequests", accept_udp_requests_);
|
||||
settings_->setValue ("UDPEnabled", udpEnabled_);
|
||||
settings_->setValue ("udpWindowToFront", udpWindowToFront_);
|
||||
settings_->setValue ("udpWindowRestore", udpWindowRestore_);
|
||||
settings_->setValue ("CalibrationIntercept", calibration_.intercept);
|
||||
@@ -1928,10 +1961,12 @@ void Configuration::impl::accept ()
|
||||
|
||||
color_CQ_ = next_color_CQ_;
|
||||
color_MyCall_ = next_color_MyCall_;
|
||||
color_TxMsg_ = next_color_TxMsg_;
|
||||
color_ReceivedMsg_ = next_color_ReceivedMsg_;
|
||||
color_DXCC_ = next_color_DXCC_;
|
||||
color_NewCall_ = next_color_NewCall_;
|
||||
|
||||
Q_EMIT self_->colors_changed();
|
||||
|
||||
rig_params_ = temp_rig_params; // now we can go live with the rig
|
||||
// related configuration parameters
|
||||
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_grid_ = ui_->grid_line_edit->text ();
|
||||
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_qth_ = ui_->qth_message_line_edit->text().toUpper();
|
||||
callsign_aging_ = ui_->callsign_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 ();
|
||||
ntrials_ = ui_->sbNtrials->value ();
|
||||
txDelay_ = ui_->sbTxDelay->value ();
|
||||
@@ -2027,11 +2063,12 @@ void Configuration::impl::accept ()
|
||||
RxBandwidth_ = ui_->sbBandwidth->value ();
|
||||
id_after_73_ = ui_->CW_id_after_73_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 ();
|
||||
monitor_off_at_startup_ = ui_->monitor_off_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 ());
|
||||
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 ();
|
||||
prompt_to_log_ = ui_->prompt_to_log_check_box->isChecked ();
|
||||
insert_blank_ = ui_->insert_blank_check_box->isChecked ();
|
||||
@@ -2060,11 +2097,15 @@ void Configuration::impl::accept ()
|
||||
pwrBandTxMemory_ = ui_->checkBoxPwrBandTxMemory->isChecked ();
|
||||
pwrBandTuneMemory_ = ui_->checkBoxPwrBandTuneMemory->isChecked ();
|
||||
opCall_=ui_->opCallEntry->text();
|
||||
|
||||
auto newUdpEnabled = ui_->udpEnable->isChecked();
|
||||
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;
|
||||
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 ();
|
||||
@@ -2073,7 +2114,7 @@ void Configuration::impl::accept ()
|
||||
udp_server_port_ = new_port;
|
||||
Q_EMIT self_->udp_server_port_changed (new_port);
|
||||
}
|
||||
|
||||
|
||||
accept_udp_requests_ = ui_->accept_udp_requests_check_box->isChecked ();
|
||||
auto new_n1mm_server = ui_->n1mm_server_name_line_edit->text ();
|
||||
n1mm_server_name_ = new_n1mm_server;
|
||||
@@ -2084,6 +2125,7 @@ void Configuration::impl::accept ()
|
||||
udpWindowToFront_ = ui_->udpWindowToFront->isChecked ();
|
||||
udpWindowRestore_ = ui_->udpWindowRestore->isChecked ();
|
||||
|
||||
|
||||
if (macros_.stringList () != next_macros_.stringList ())
|
||||
{
|
||||
macros_.setStringList (next_macros_.stringList ());
|
||||
@@ -2101,6 +2143,8 @@ void Configuration::impl::accept ()
|
||||
{
|
||||
stations_.station_list(next_stations_.station_list ());
|
||||
stations_.sort (StationList::switch_at_column);
|
||||
|
||||
Q_EMIT self_->band_schedule_changed(this->stations_);
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
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 ())
|
||||
{
|
||||
next_color_CQ_ = new_color;
|
||||
@@ -2153,7 +2197,7 @@ void Configuration::impl::on_pbCQmsg_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 ())
|
||||
{
|
||||
next_color_MyCall_ = new_color;
|
||||
@@ -2163,11 +2207,11 @@ void Configuration::impl::on_pbMyCall_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 ())
|
||||
{
|
||||
next_color_TxMsg_ = new_color;
|
||||
ui_->labTx->setStyleSheet(QString("background: %1").arg(next_color_TxMsg_.name()));
|
||||
next_color_ReceivedMsg_ = new_color;
|
||||
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 ()
|
||||
{
|
||||
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
|
||||
, QFontDialog::MonospacedFonts
|
||||
#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 ()
|
||||
{
|
||||
ui_->add_macro_line_edit->setText (ui_->add_macro_line_edit->text ().toUpper ());
|
||||
|
||||
+10
-4
@@ -102,6 +102,7 @@ public:
|
||||
int activity_aging() const;
|
||||
int callsign_aging() const;
|
||||
QString my_qth () const;
|
||||
QString reply () const;
|
||||
QFont text_font () const;
|
||||
QFont decoded_text_font () const;
|
||||
qint32 id_interval () const;
|
||||
@@ -112,12 +113,13 @@ public:
|
||||
double txDelay() const;
|
||||
bool id_after_73 () const;
|
||||
bool tx_QSY_allowed () const;
|
||||
bool spot_to_psk_reporter () const;
|
||||
void set_spot_to_psk_reporter (bool);
|
||||
bool spot_to_reporting_networks () const;
|
||||
void set_spot_to_reporting_networks (bool);
|
||||
bool transmit_directed() const;
|
||||
bool autoreply_off_at_startup () const;
|
||||
bool monitor_off_at_startup () const;
|
||||
bool monitor_last_used () const;
|
||||
bool log_as_RTTY () const;
|
||||
bool log_as_DATA () const;
|
||||
bool report_in_comments () const;
|
||||
bool prompt_to_log () const;
|
||||
bool insert_blank () const;
|
||||
@@ -156,6 +158,7 @@ public:
|
||||
bool accept_udp_requests () const;
|
||||
bool udpWindowToFront () const;
|
||||
bool udpWindowRestore () const;
|
||||
bool udpEnabled () const;
|
||||
Bands * bands ();
|
||||
Bands const * bands () const;
|
||||
IARURegions::Region region () const;
|
||||
@@ -172,7 +175,7 @@ public:
|
||||
Type2MsgGen type_2_msg_gen () const;
|
||||
QColor color_CQ () const;
|
||||
QColor color_MyCall () const;
|
||||
QColor color_TxMsg () const;
|
||||
QColor color_ReceivedMsg () const;
|
||||
QColor color_DXCC () const;
|
||||
QColor color_NewCall () const;
|
||||
bool pwrBandTxMemory () const;
|
||||
@@ -267,6 +270,7 @@ public:
|
||||
//
|
||||
Q_SIGNAL void 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
|
||||
@@ -274,6 +278,8 @@ public:
|
||||
Q_SIGNAL void udp_server_changed (QString const& udp_server);
|
||||
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
|
||||
|
||||
+487
-459
File diff suppressed because it is too large
Load Diff
+8
-8
@@ -26,16 +26,16 @@ namespace
|
||||
{
|
||||
FrequencyList_v2::FrequencyItems const default_frequency_list =
|
||||
{
|
||||
{ 1838000, Modes::FT8CALL, IARURegions::ALL}, // 2 below
|
||||
{ 3580000, Modes::FT8CALL, IARURegions::ALL}, // 7 above
|
||||
{ 7080000, Modes::FT8CALL, IARURegions::ALL}, // 7 above
|
||||
{ 1842000, Modes::FT8CALL, IARURegions::ALL}, // 2 above
|
||||
{ 3578000, Modes::FT8CALL, IARURegions::ALL}, // 5 above
|
||||
{ 7078000, Modes::FT8CALL, IARURegions::ALL}, // 4 above
|
||||
{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
|
||||
{21080000, Modes::FT8CALL, IARURegions::ALL}, // 6 above
|
||||
{24920000, Modes::FT8CALL, IARURegions::ALL}, // 5 above
|
||||
{28080000, Modes::FT8CALL, IARURegions::ALL}, // 6 above
|
||||
{50300000, Modes::FT8CALL, IARURegions::ALL}, // 13 below
|
||||
{21078000, Modes::FT8CALL, IARURegions::ALL}, // 4 above
|
||||
{24922000, Modes::FT8CALL, IARURegions::ALL}, // 9 above
|
||||
{28078000, Modes::FT8CALL, IARURegions::ALL}, // 4 above
|
||||
{50318000, Modes::FT8CALL, IARURegions::ALL}, // 5 above
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ class MaidenheadLocatorValidator final
|
||||
: public QValidator
|
||||
{
|
||||
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
|
||||
, Length length = Length::subsquare
|
||||
, Length required = Length::square);
|
||||
|
||||
@@ -329,6 +329,7 @@ auto MessageClient::server_port () const -> port_type
|
||||
|
||||
void MessageClient::set_server (QString const& server)
|
||||
{
|
||||
qDebug() << "server changed to" << server;
|
||||
m_->server_.clear ();
|
||||
m_->server_string_ = server;
|
||||
if (!server.isEmpty ())
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
@@ -1,6 +1,6 @@
|
||||
# Version number components
|
||||
set (WSJTX_VERSION_MAJOR 0)
|
||||
set (WSJTX_VERSION_MINOR 4)
|
||||
set (WSJTX_VERSION_PATCH 1)
|
||||
set (WSJTX_VERSION_MINOR 5)
|
||||
set (WSJTX_VERSION_PATCH 0)
|
||||
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
|
||||
|
||||
@@ -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
@@ -277,7 +277,7 @@ void DisplayText::displayDecodedText(DecodedText const& decodedText, QString con
|
||||
|
||||
|
||||
void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 txFreq,
|
||||
QColor color_TxMsg, bool bFastMode)
|
||||
QColor color_ReceivedMsg, bool bFastMode)
|
||||
{
|
||||
QString t1=" @ ";
|
||||
if(modeTx=="FT8") t1=" ~ ";
|
||||
@@ -297,7 +297,7 @@ void DisplayText::displayTransmittedText(QString text, QString modeTx, qint32 tx
|
||||
t = QDateTime::currentDateTimeUtc().toString("hhmm") + \
|
||||
" Tx " + t2 + t1 + text;
|
||||
}
|
||||
appendText (t, color_TxMsg);
|
||||
appendText (t, color_ReceivedMsg);
|
||||
}
|
||||
|
||||
void DisplayText::displayQSY(QString text)
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ public:
|
||||
LogBook const& logBook, QColor color_CQ, QColor color_MyCall,
|
||||
QColor color_DXCC, QColor color_NewCall, bool ppfx, bool bCQonly=false);
|
||||
void displayTransmittedText(QString text, QString modeTx, qint32 txFreq,
|
||||
QColor color_TxMsg, bool bFastMode);
|
||||
QColor color_ReceivedMsg, bool bFastMode);
|
||||
void displayQSY(QString text);
|
||||
void displayFoxToBeCalled(QString t, QColor bg);
|
||||
|
||||
|
||||
+1
-1
@@ -75,7 +75,7 @@ void LogQSO::initLogQSO(QString const& hisCall, QString const& hisGrid, QString
|
||||
if(rptRcvd!="") t+=" Rcvd: " + rptRcvd;
|
||||
ui->comments->setText(t);
|
||||
}
|
||||
if(toRTTY) mode="RTTY";
|
||||
if(toRTTY) mode="DATA";
|
||||
ui->mode->setText(mode);
|
||||
ui->sent->setText(rptSent);
|
||||
ui->rcvd->setText(rptRcvd);
|
||||
|
||||
+995
-311
File diff suppressed because it is too large
Load Diff
+34
-8
@@ -44,6 +44,7 @@
|
||||
#include "qpriorityqueue.h"
|
||||
#include "varicode.h"
|
||||
#include "MessageClient.hpp"
|
||||
#include "APRSISClient.h"
|
||||
|
||||
#define NUM_JT4_SYMBOLS 206 //(72+31)*2, embedded sync
|
||||
#define NUM_JT65_SYMBOLS 126 //63 data + 63 sync
|
||||
@@ -132,14 +133,19 @@ public slots:
|
||||
|
||||
void logCallActivity(CallDetail d, bool spot=true);
|
||||
QString lookupCallInCompoundCache(QString const &call);
|
||||
void cacheActivity(QString key);
|
||||
void restoreActivity(QString key);
|
||||
void clearActivity();
|
||||
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);
|
||||
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 resetMessage();
|
||||
void resetMessageUI();
|
||||
void restoreMessage();
|
||||
bool ensureCallsignSet(bool alert=true);
|
||||
void createMessage(QString const& text);
|
||||
void createMessageTransmitQueue(QString const& text);
|
||||
void resetMessageTransmitQueue();
|
||||
@@ -164,7 +170,7 @@ private slots:
|
||||
void on_actionShow_Waterfall_triggered(bool checked);
|
||||
void on_actionReset_Window_Sizes_triggered();
|
||||
void on_actionSettings_triggered();
|
||||
void preparePSKReporter();
|
||||
void prepareSpotting();
|
||||
void on_spotButton_clicked(bool checked);
|
||||
void on_monitorButton_clicked (bool);
|
||||
void on_actionAbout_triggered();
|
||||
@@ -252,9 +258,14 @@ private slots:
|
||||
void on_rbFreeText_clicked(bool checked);
|
||||
void on_clearAction_triggered(QObject * sender);
|
||||
void on_cqMacroButton_clicked();
|
||||
void on_qtcMacroButton_clicked();
|
||||
void on_replyMacroButton_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_macrosMacroButton_pressed();
|
||||
void on_tableWidgetRXAll_cellClicked(int row, int col);
|
||||
@@ -277,7 +288,7 @@ private slots:
|
||||
void pauseBacon();
|
||||
void checkBacon();
|
||||
void prepareBacon();
|
||||
QString calculateDistance(QString const& grid);
|
||||
QString calculateDistance(QString const& grid, int *pDistance=nullptr);
|
||||
void on_rptSpinBox_valueChanged(int n);
|
||||
void killFile();
|
||||
void on_tuneButton_clicked (bool);
|
||||
@@ -353,6 +364,7 @@ private slots:
|
||||
void on_sbMax_dB_valueChanged(int n);
|
||||
void on_pbFoxReset_clicked();
|
||||
void on_comboBoxHoundSort_activated (int index);
|
||||
void expiry_warning_message ();
|
||||
void not_GA_warning_message ();
|
||||
|
||||
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
|
||||
QQueue<QString> m_txFrameQueue; // frames to be sent
|
||||
QQueue<ActivityDetail> m_rxActivityQueue; // all rx activity queue
|
||||
@@ -730,12 +748,17 @@ private:
|
||||
QMap<QString, QString> m_compoundCallCache; // base callsign -> compound callsign
|
||||
QCache<QString, QDateTime> m_txAllcallCommandCache; // callsign -> last tx
|
||||
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
|
||||
QMap<int, int> m_rxFrameBlockNumbers; // freq -> block
|
||||
QMap<int, QList<ActivityDetail>> m_bandActivity; // freq -> [(text, last timestamp), ...]
|
||||
QMap<int, MessageBuffer> m_messageBuffer; // freq -> (cmd, [frames, ...])
|
||||
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
|
||||
int m_previousFreq;
|
||||
bool m_shouldRestoreFreq;
|
||||
@@ -791,6 +814,7 @@ private:
|
||||
QTimer m_heartbeat;
|
||||
MessageClient * m_messageClient;
|
||||
PSK_Reporter *psk_Reporter;
|
||||
APRSISClient * m_aprsClient;
|
||||
DisplayManual m_manual;
|
||||
QHash<QString, QVariant> m_pwrBandTxMemory; // Remembers power level by band
|
||||
QHash<QString, QVariant> m_pwrBandTuneMemory; // Remembers power level by band for tuning
|
||||
@@ -817,8 +841,10 @@ private:
|
||||
void transmit (double snr = 99.);
|
||||
void rigFailure (QString const& reason);
|
||||
void pskSetLocal ();
|
||||
void aprsSetLocal ();
|
||||
void pskPost(DecodedText const& decodedtext);
|
||||
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();
|
||||
void displayDialFrequency ();
|
||||
void transmitDisplay (bool);
|
||||
@@ -834,8 +860,8 @@ private:
|
||||
QString callsignSelected();
|
||||
bool isRecentOffset(int offset);
|
||||
void markOffsetRecent(int offset);
|
||||
bool isDirectedOffset(int offset);
|
||||
void markOffsetDirected(int offset);
|
||||
bool isDirectedOffset(int offset, bool *pIsAllCall);
|
||||
void markOffsetDirected(int offset, bool isAllCall);
|
||||
void processActivity(bool force=false);
|
||||
void processRxActivity();
|
||||
void processCompoundActivity();
|
||||
|
||||
+68
-5
@@ -221,7 +221,7 @@ QPushButton[oob="true"] {
|
||||
</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>14.074 000</string>
|
||||
<string>14.078 000</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
@@ -508,6 +508,9 @@ color : white;
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable or disable the receiver</p></body></html></string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
font-family: helvetica;
|
||||
@@ -640,6 +643,9 @@ background-color: yellow;
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Transmit a tuning tone</p></body></html></string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
font-family: helvetica;
|
||||
@@ -701,6 +707,9 @@ background-color: yellow;
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable or disable automatic station replies to directed queries</p></body></html></string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
font-family: helvetica;
|
||||
@@ -761,6 +770,9 @@ background-color: #6699ff;
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable or disable spotting of callsigns heard to PSKReporter</p></body></html></string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
font-family: helvetica;
|
||||
@@ -821,6 +833,9 @@ background-color: #00ff00;
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Enable or disable the automatic beacon</p></body></html></string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
font-family: helvetica;
|
||||
@@ -881,6 +896,9 @@ background-color: #6699ff;
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Insert a new entry into the log</p></body></html></string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {
|
||||
font-family: helvetica;
|
||||
@@ -951,6 +969,9 @@ background-color: #00ff00;
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Received band activity is displayed with time since last heard, SNR, and the text received for each frequency offset in the passband.</p></body></html></string>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QAbstractScrollArea::AdjustToContentsOnFirstShow</enum>
|
||||
</property>
|
||||
@@ -1107,6 +1128,9 @@ QTextEdit[transmitting="true"] {
|
||||
<pointsize>12</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Received callsigns are displayed with time since last heard, SNR, and grid locator (if reported).</p></body></html></string>
|
||||
</property>
|
||||
<property name="autoScroll">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@@ -1154,6 +1178,11 @@ QTextEdit[transmitting="true"] {
|
||||
<string>Callsign</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Offset</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Age</string>
|
||||
@@ -1232,6 +1261,12 @@ QTextEdit[transmitting="true"] {
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Send your station location message</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>QTH</string>
|
||||
</property>
|
||||
@@ -1245,6 +1280,9 @@ QTextEdit[transmitting="true"] {
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Send a CQ message</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CQ</string>
|
||||
</property>
|
||||
@@ -1261,24 +1299,27 @@ QTextEdit[transmitting="true"] {
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Stop transmitting</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Halt</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QPushButton" name="qtcMacroButton">
|
||||
<widget class="QPushButton" name="replyMacroButton">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="visible">
|
||||
<bool>true</bool>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Reply to a CQ</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>QTC</string>
|
||||
<string>Reply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -1290,6 +1331,9 @@ QTextEdit[transmitting="true"] {
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Send a macro</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Macros</string>
|
||||
</property>
|
||||
@@ -1306,6 +1350,9 @@ QTextEdit[transmitting="true"] {
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Start transmitting</p></body></html></string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton:checked {
|
||||
background-color: #00ff00;
|
||||
@@ -1330,6 +1377,9 @@ background:yellow;
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Send a directed message to another station</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Directed</string>
|
||||
</property>
|
||||
@@ -4308,6 +4358,9 @@ list. The list can be maintained in Settings (F2).</string>
|
||||
<property name="title">
|
||||
<string>Window</string>
|
||||
</property>
|
||||
<addaction name="actionSort_Band_Activity"/>
|
||||
<addaction name="actionSort_Call_Activity"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionShow_Band_Activity"/>
|
||||
<addaction name="actionShow_Call_Activity"/>
|
||||
<addaction name="actionShow_Waterfall"/>
|
||||
@@ -5003,6 +5056,16 @@ list. The list can be maintained in Settings (F2).</string>
|
||||
<string>Reset Window Sizes</string>
|
||||
</property>
|
||||
</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>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
|
||||
+77
-5
@@ -50,6 +50,8 @@ CPlotter::CPlotter(QWidget *parent) : //CPlotter Constructor
|
||||
setAttribute(Qt::WA_NoSystemBackground, true);
|
||||
m_bReplot=false;
|
||||
|
||||
setMouseTracking(true);
|
||||
|
||||
// contextual pop up menu
|
||||
setContextMenuPolicy (Qt::CustomContextMenu);
|
||||
connect (this, &QWidget::customContextMenuRequested, [this] (QPoint const& pos) {
|
||||
@@ -91,8 +93,10 @@ void CPlotter::resizeEvent(QResizeEvent* ) //resizeEvent()
|
||||
m_h1=m_h-m_h2;
|
||||
// m_line=0;
|
||||
|
||||
m_FullOverlayPixmap = QPixmap(m_Size.width(), m_h);
|
||||
m_FullOverlayPixmap.fill(Qt::transparent);
|
||||
m_DialOverlayPixmap = QPixmap(m_Size.width(), m_h);
|
||||
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.fill(Qt::black);
|
||||
m_WaterfallPixmap = QPixmap(m_Size.width(), m_h1);
|
||||
@@ -117,7 +121,12 @@ void CPlotter::paintEvent(QPaintEvent *) // paint
|
||||
painter.drawPixmap(0,m_h1,m_2DPixmap);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -329,6 +338,7 @@ void CPlotter::DrawOverlay() //DrawOverlay()
|
||||
QPen penOrange(QColor(255,165,0),3);
|
||||
QPen penGreen(Qt::green, 3); //Mark Tol range with green line
|
||||
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);
|
||||
painter.initFrom(this);
|
||||
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;
|
||||
for( int i=1; i<minor*m_hdivs; i++) { //minor ticks
|
||||
x = i*pixperdiv/minor;
|
||||
painter0.drawLine(x,24,x,30);
|
||||
painter0.drawLine(x,22,x,30);
|
||||
}
|
||||
|
||||
//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"){
|
||||
int fwidth=XfromFreq(m_rxFreq+bw)-XfromFreq(m_rxFreq);
|
||||
QPainter overPainter(&m_FullOverlayPixmap);
|
||||
QPainter overPainter(&m_DialOverlayPixmap);
|
||||
overPainter.initFrom(this);
|
||||
overPainter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
overPainter.fillRect(0, 0, m_Size.width(), m_h, Qt::transparent);
|
||||
@@ -571,6 +589,20 @@ void CPlotter::DrawOverlay() //DrawOverlay()
|
||||
overPainter.setPen(penRed);
|
||||
overPainter.drawLine(0, 26, fwidth, 26);
|
||||
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
|
||||
|
||||
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)
|
||||
{
|
||||
if (Qt::LeftButton == event->button ()) {
|
||||
|
||||
@@ -95,6 +95,9 @@ protected:
|
||||
//re-implemented widget event handlers
|
||||
void paintEvent(QPaintEvent *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 mouseDoubleClickEvent (QMouseEvent * event) override;
|
||||
|
||||
@@ -128,7 +131,8 @@ private:
|
||||
qint32 m_ia;
|
||||
qint32 m_ib;
|
||||
|
||||
QPixmap m_FullOverlayPixmap;
|
||||
QPixmap m_DialOverlayPixmap;
|
||||
QPixmap m_HoverOverlayPixmap;
|
||||
QPixmap m_WaterfallPixmap;
|
||||
QPixmap m_2DPixmap;
|
||||
QPixmap m_ScalePixmap;
|
||||
@@ -174,6 +178,7 @@ private:
|
||||
qint32 m_startFreq;
|
||||
qint32 m_tol;
|
||||
qint32 m_j;
|
||||
qint32 m_lastMouseX;
|
||||
|
||||
char m_sutc[6];
|
||||
};
|
||||
|
||||
+39
-12
@@ -30,7 +30,7 @@
|
||||
const int nalphabet = 41;
|
||||
QString alphabet = {"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ+-./?"}; // alphabet to encode _into_ for FT8 freetext transmission
|
||||
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 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 ]))"};
|
||||
@@ -44,18 +44,28 @@ QMap<QString, int> directed_cmds = {
|
||||
{"@", 1 }, // query qth
|
||||
{"&", 2 }, // query station message
|
||||
{"$", 3 }, // query station(s) heard
|
||||
{"^", 4 }, // query grid
|
||||
{"%", 5 }, // query pwr
|
||||
// 4.
|
||||
{"|", 6 }, // retransmit message
|
||||
{"!", 7 }, // alert message
|
||||
{"#", 8 }, // all or nothing message
|
||||
|
||||
// {"=", 9 }, // unused? (can we even use equals?)
|
||||
// {"/", 10 }, // unused? (can we even use stroke?)
|
||||
// {"=", 9 }, // unused
|
||||
// {"/", 10 }, // unused
|
||||
// {"/", 11 }, // unused
|
||||
// {"/", 12 }, // unused
|
||||
// {"/", 13 }, // unused
|
||||
|
||||
// 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
|
||||
{" RR", 21 }, // roger roger (not visible in UI but still exists)
|
||||
{" RR", 21 }, // roger roger
|
||||
{" QSL?", 22 }, // do you copy?
|
||||
{" QSL", 23 }, // i copy
|
||||
{" PWR", 24 }, // power level
|
||||
@@ -68,12 +78,21 @@ QMap<QString, int> directed_cmds = {
|
||||
{" ", 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 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_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)?");
|
||||
@@ -947,7 +966,7 @@ QString Varicode::unpackCallsign(quint32 value){
|
||||
return callsign;
|
||||
}
|
||||
|
||||
QString deg2grid(float dlong, float dlat){
|
||||
QString Varicode::deg2grid(float dlong, float dlat){
|
||||
QChar grid[6];
|
||||
|
||||
if(dlong < -180){
|
||||
@@ -980,7 +999,7 @@ QString deg2grid(float dlong, float dlat){
|
||||
return QString(grid, 6);
|
||||
}
|
||||
|
||||
QPair<float, float> grid2deg(QString const &grid){
|
||||
QPair<float, float> Varicode::grid2deg(QString const &grid){
|
||||
QPair<float, float> longLat;
|
||||
|
||||
QString g = grid;
|
||||
@@ -1012,7 +1031,7 @@ quint16 Varicode::packGrid(QString const& value){
|
||||
return (1<<15)-1;
|
||||
}
|
||||
|
||||
auto pair = grid2deg(grid.left(4));
|
||||
auto pair = Varicode::grid2deg(grid.left(4));
|
||||
int ilong = pair.first;
|
||||
int ilat = pair.second + 90;
|
||||
|
||||
@@ -1027,7 +1046,7 @@ QString Varicode::unpackGrid(quint16 value){
|
||||
float dlat = value % 180 - 90;
|
||||
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
|
||||
@@ -1115,6 +1134,14 @@ bool Varicode::isCommandBuffered(const QString &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
|
||||
// BEACON EM73
|
||||
QString Varicode::packBeaconMessage(QString const &text, const QString &callsign, int *n){
|
||||
|
||||
+6
-3
@@ -41,11 +41,11 @@ public:
|
||||
"FrameBeacon",
|
||||
"FrameCompound",
|
||||
"FrameCompoundDirected",
|
||||
"FrameDirectedPositive",
|
||||
"FrameDirectedNegative",
|
||||
"FrameDirected",
|
||||
"FrameReservedA",
|
||||
"FrameDataUnpadded",
|
||||
"FrameDataPadded",
|
||||
"FrameReserved"
|
||||
"FrameReservedB"
|
||||
};
|
||||
|
||||
if(type > FrameTypeMax){
|
||||
@@ -109,6 +109,8 @@ public:
|
||||
static quint32 packCallsign(QString const& 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 QString unpackGrid(quint16 value);
|
||||
|
||||
@@ -119,6 +121,7 @@ public:
|
||||
|
||||
static bool isCommandAllowed(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 QStringList unpackBeaconMessage(const QString &text, quint8 *pType, bool *isAlt);
|
||||
|
||||
+5
-3
@@ -80,14 +80,14 @@ WideGraph::WideGraph(QSettings * settings, QWidget *parent) :
|
||||
ui->widePlot->setBinsPerPixel(nbpp);
|
||||
ui->sbPercent2dPlot->setValue(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());
|
||||
m_waterfallPalette=m_settings->value("WaterfallPalette","Default").toString();
|
||||
m_userPalette = WFPalette {m_settings->value("UserPalette").value<WFPalette::Colours> ()};
|
||||
m_fMinPerBand = m_settings->value ("FminPerBand").toHash ();
|
||||
setRxRange ();
|
||||
ui->controls_widget->setVisible(!m_settings->value("HideControls", true).toBool());
|
||||
ui->cbControls->setChecked(!m_settings->value("HideControls", true).toBool());
|
||||
ui->controls_widget->setVisible(!m_settings->value("HideControls", false).toBool());
|
||||
ui->cbControls->setChecked(!m_settings->value("HideControls", false).toBool());
|
||||
}
|
||||
|
||||
int index=0;
|
||||
@@ -212,6 +212,8 @@ void WideGraph::on_offsetSpinBox_valueChanged(int n){
|
||||
return;
|
||||
}
|
||||
|
||||
n = qMax(500, n);
|
||||
|
||||
setRxFreq(n);
|
||||
setTxFreq(n);
|
||||
setFreq2(n, n);
|
||||
|
||||
@@ -177,6 +177,9 @@
|
||||
<property name="singleStep">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>500</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="12">
|
||||
|
||||
@@ -70,7 +70,9 @@ SOURCES += \
|
||||
EqualizationToolsDialog.cpp \
|
||||
varicode.cpp \
|
||||
NetworkMessage.cpp \
|
||||
MessageClient.cpp
|
||||
MessageClient.cpp \
|
||||
SelfDestructMessageBox.cpp \
|
||||
APRSISClient.cpp
|
||||
|
||||
HEADERS += qt_helpers.hpp \
|
||||
pimpl_h.hpp pimpl_impl.hpp \
|
||||
@@ -92,7 +94,9 @@ HEADERS += qt_helpers.hpp \
|
||||
qpriorityqueue.h \
|
||||
crc.h \
|
||||
NetworkMessage.hpp \
|
||||
MessageClient.hpp
|
||||
MessageClient.hpp \
|
||||
SelfDestructMessageBox.h \
|
||||
APRSISClient.h
|
||||
|
||||
|
||||
INCLUDEPATH += qmake_only
|
||||
|
||||
Reference in New Issue
Block a user