diff --git a/CMakeLists.txt b/CMakeLists.txt
index a91121d7d..2dd2e4e13 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -683,6 +683,7 @@ set (message_aggregator_CXXSRCS
UDPExamples/DecodesModel.cpp
UDPExamples/BeaconsModel.cpp
UDPExamples/ClientWidget.cpp
+ MaidenheadLocatorValidator.cpp
)
set (message_aggregator_STYLESHEETS
diff --git a/Configuration.cpp b/Configuration.cpp
index 3d19c0878..b1cab5b65 100644
--- a/Configuration.cpp
+++ b/Configuration.cpp
@@ -524,6 +524,7 @@ private:
CalibrationParams calibration_;
bool frequency_calibration_disabled_; // not persistent
unsigned transceiver_command_number_;
+ QString dynamic_grid_;
// configuration fields that we publish
QString my_callsign_;
@@ -569,6 +570,7 @@ private:
bool bHound_;
bool x2ToneSpacing_;
bool x4ToneSpacing_;
+ bool use_dynamic_grid_;
QString opCall_;
QString udp_server_name_;
port_type udp_server_port_;
@@ -627,7 +629,6 @@ bool Configuration::restart_audio_input () const {return m_->restart_sound_input
bool Configuration::restart_audio_output () const {return m_->restart_sound_output_device_;}
auto Configuration::type_2_msg_gen () const -> Type2MsgGen {return m_->type_2_msg_gen_;}
QString Configuration::my_callsign () const {return m_->my_callsign_;}
-QString Configuration::my_grid () const {return m_->my_grid_;}
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_;}
@@ -797,6 +798,22 @@ bool Configuration::valid_n1mm_info () const
return(!(server_name.trimmed().isEmpty() || port_number == 0));
}
+QString Configuration::my_grid() const
+{
+ auto the_grid = m_->my_grid_;
+ if (m_->use_dynamic_grid_ && m_->dynamic_grid_.size () >= 4) {
+ the_grid = m_->dynamic_grid_;
+ }
+ return the_grid;
+}
+
+void Configuration::set_location (QString const& grid_descriptor)
+{
+ // change the dynamic grid
+ qDebug () << "Configuration::set_location - location:" << grid_descriptor;
+ m_->dynamic_grid_ = grid_descriptor.trimmed ();
+}
+
namespace
{
#if defined (Q_OS_MAC)
@@ -1102,6 +1119,7 @@ void Configuration::impl::initialize_models ()
ui_->grid_line_edit->setPalette (pal);
ui_->callsign_line_edit->setText (my_callsign_);
ui_->grid_line_edit->setText (my_grid_);
+ ui_->use_dynamic_grid->setChecked(use_dynamic_grid_);
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()));
@@ -1316,6 +1334,7 @@ void Configuration::impl::read_settings ()
spot_to_psk_reporter_ = settings_->value ("PSKReporter", false).toBool ();
id_after_73_ = settings_->value ("After73", false).toBool ();
tx_QSY_allowed_ = settings_->value ("TxQSYAllowed", false).toBool ();
+ use_dynamic_grid_ = settings_->value ("AutoGrid", false).toBool ();
macros_.setStringList (settings_->value ("Macros", QStringList {"TNX 73 GL"}).toStringList ());
@@ -1496,6 +1515,7 @@ void Configuration::impl::write_settings ()
settings_->setValue ("pwrBandTxMemory", pwrBandTxMemory_);
settings_->setValue ("pwrBandTuneMemory", pwrBandTuneMemory_);
settings_->setValue ("Region", QVariant::fromValue (region_));
+ settings_->setValue ("AutoGrid", use_dynamic_grid_);
}
void Configuration::impl::set_rig_invariants ()
@@ -1931,7 +1951,14 @@ void Configuration::impl::accept ()
stations_.station_list(next_stations_.station_list ());
stations_.sort (StationList::band_column);
}
-
+
+ if (ui_->use_dynamic_grid->isChecked() && !use_dynamic_grid_ )
+ {
+ // turning on so clear it so only the next location update gets used
+ dynamic_grid_.clear ();
+ }
+ use_dynamic_grid_ = ui_->use_dynamic_grid->isChecked();
+
write_settings (); // make visible to all
}
diff --git a/Configuration.hpp b/Configuration.hpp
index a87e33814..886bed085 100644
--- a/Configuration.hpp
+++ b/Configuration.hpp
@@ -192,6 +192,9 @@ public:
// Set the calibration parameters and enable calibration corrections.
void set_calibration (CalibrationParams);
+ // Set the dynamic grid which is only used if configuration setting is enabled.
+ void set_location (QString const&);
+
// This method queries if a CAT and PTT connection is operational.
bool is_transceiver_online () const;
diff --git a/Configuration.ui b/Configuration.ui
index c31fe3f22..2c1f9b173 100644
--- a/Configuration.ui
+++ b/Configuration.ui
@@ -80,11 +80,22 @@
+ -
+
+
-
+
+
+ Check to allow grid changes from external programs
+
+
+ AutoGrid
+
+
+
+
+
-
-
-
-
-
-
@@ -95,6 +106,9 @@
+ -
+
+
@@ -2599,6 +2613,7 @@ soundcard changes
configuration_tabs
callsign_line_edit
grid_line_edit
+ use_dynamic_grid
region_combo_box
type_2_msg_gen_combo_box
insert_blank_check_box
diff --git a/MessageClient.cpp b/MessageClient.cpp
index 799179ab7..2b6d9e308 100644
--- a/MessageClient.cpp
+++ b/MessageClient.cpp
@@ -207,6 +207,17 @@ void MessageClient::impl::parse_message (QByteArray const& msg)
}
break;
+ case NetworkMessage::Location:
+ {
+ QByteArray location;
+ in >> location;
+ if (check_status (in) != Fail)
+ {
+ Q_EMIT self_->location (QString::fromUtf8 (location));
+ }
+ }
+ break;
+
default:
// Ignore
//
@@ -433,7 +444,9 @@ void MessageClient::clear_decodes ()
void MessageClient::qso_logged (QDateTime time_off, QString const& dx_call, QString const& dx_grid
, Frequency dial_frequency, QString const& mode, QString const& report_sent
, QString const& report_received, QString const& tx_power
- , QString const& comments, QString const& name, QDateTime time_on, QString const& operator_call)
+ , QString const& comments, QString const& name, QDateTime time_on
+ , QString const& operator_call, QString const& my_call
+ , QString const& my_grid)
{
if (m_->server_port_ && !m_->server_string_.isEmpty ())
{
@@ -441,7 +454,19 @@ void MessageClient::qso_logged (QDateTime time_off, QString const& dx_call, QStr
NetworkMessage::Builder out {&message, NetworkMessage::QSOLogged, m_->id_, m_->schema_};
out << time_off << dx_call.toUtf8 () << dx_grid.toUtf8 () << dial_frequency << mode.toUtf8 ()
<< report_sent.toUtf8 () << report_received.toUtf8 () << tx_power.toUtf8 () << comments.toUtf8 ()
- << name.toUtf8 () << time_on << operator_call.toUtf8 ();
+ << name.toUtf8 () << time_on << operator_call.toUtf8 () << my_call.toUtf8 () << my_grid.toUtf8 ();
+ m_->send_message (out, message);
+ }
+}
+
+void MessageClient::logged_ADIF (QByteArray const& ADIF_record)
+{
+ if (m_->server_port_ && !m_->server_string_.isEmpty ())
+ {
+ QByteArray message;
+ NetworkMessage::Builder out {&message, NetworkMessage::LoggedADIF, m_->id_, m_->schema_};
+ QByteArray ADIF {"\n3.0.7\nWSJT-X\n\n" + ADIF_record + " "};
+ out << ADIF;
m_->send_message (out, message);
}
}
diff --git a/MessageClient.hpp b/MessageClient.hpp
index 6cb3ea87f..f0719ac55 100644
--- a/MessageClient.hpp
+++ b/MessageClient.hpp
@@ -62,7 +62,12 @@ public:
Q_SLOT void qso_logged (QDateTime time_off, QString const& dx_call, QString const& dx_grid
, Frequency dial_frequency, QString const& mode, QString const& report_sent
, QString const& report_received, QString const& tx_power, QString const& comments
- , QString const& name, QDateTime time_on, QString const& operator_call);
+ , QString const& name, QDateTime time_on, QString const& operator_call
+ , QString const& my_call, QString const& my_grid);
+
+ // ADIF_record argument should be valid ADIF excluding any end
+ // of record marker
+ Q_SLOT void logged_ADIF (QByteArray const& ADIF_record);
// this slot may be used to send arbitrary UDP datagrams to and
// destination allowing the underlying socket to be used for general
@@ -94,6 +99,11 @@ public:
// lookup fails
Q_SIGNAL void error (QString const&) const;
+ // this signal is emitted if the message obtains a location from a
+ // server. (It doesn't have to be new, could be a periodic location
+ // update)
+ Q_SIGNAL void location (QString const&);
+
private:
class impl;
pimpl m_;
diff --git a/MessageServer.cpp b/MessageServer.cpp
index e6e100762..724da4afc 100644
--- a/MessageServer.cpp
+++ b/MessageServer.cpp
@@ -292,14 +292,18 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
QByteArray name;
QDateTime time_on; // Note: LOTW uses TIME_ON for their +/- 30-minute time window
QByteArray operator_call;
+ QByteArray my_call;
+ QByteArray my_grid;
in >> time_off >> dx_call >> dx_grid >> dial_frequency >> mode >> report_sent >> report_received
- >> tx_power >> comments >> name >> time_on >> operator_call;
+ >> tx_power >> comments >> name >> time_on >> operator_call >> my_call >> my_grid;
if (check_status (in) != Fail)
{
Q_EMIT self_->qso_logged (id, time_off, QString::fromUtf8 (dx_call), QString::fromUtf8 (dx_grid)
, dial_frequency, QString::fromUtf8 (mode), QString::fromUtf8 (report_sent)
, QString::fromUtf8 (report_received), QString::fromUtf8 (tx_power)
- , QString::fromUtf8 (comments), QString::fromUtf8 (name), time_on, QString::fromUtf8 (operator_call));
+ , QString::fromUtf8 (comments), QString::fromUtf8 (name), time_on
+ , QString::fromUtf8 (operator_call), QString::fromUtf8 (my_call)
+ , QString::fromUtf8 (my_grid));
}
}
break;
@@ -309,6 +313,17 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s
clients_.remove (id);
break;
+ case NetworkMessage::LoggedADIF:
+ {
+ QByteArray ADIF;
+ in >> ADIF;
+ if (check_status (in) != Fail)
+ {
+ Q_EMIT self_->logged_ADIF (id, ADIF);
+ }
+ }
+ break;
+
default:
// Ignore
break;
@@ -453,3 +468,15 @@ void MessageServer::free_text (QString const& id, QString const& text, bool send
m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_);
}
}
+
+void MessageServer::location (QString const& id, QString const& loc)
+{
+ auto iter = m_->clients_.find (id);
+ if (iter != std::end (m_->clients_))
+ {
+ QByteArray message;
+ NetworkMessage::Builder out {&message, NetworkMessage::Location, id, (*iter).negotiated_schema_number_};
+ out << loc.toUtf8 ();
+ m_->send_message (out, message, iter.value ().sender_address_, (*iter).sender_port_);
+ }
+}
diff --git a/MessageServer.hpp b/MessageServer.hpp
index 83fb4ff83..77c976fa4 100644
--- a/MessageServer.hpp
+++ b/MessageServer.hpp
@@ -59,6 +59,9 @@ public:
// message and optionally send it ASAP
Q_SLOT void free_text (QString const& id, QString const& text, bool send);
+ // ask the client with identification 'id' to set the location provided
+ Q_SLOT void location (QString const& id, QString const& location);
+
// the following signals are emitted when a client broadcasts the
// matching message
Q_SIGNAL void client_opened (QString const& id, QString const& version, QString const& revision);
@@ -77,8 +80,10 @@ public:
Q_SIGNAL void qso_logged (QString const& id, QDateTime time_off, QString const& dx_call, QString const& dx_grid
, Frequency dial_frequency, QString const& mode, QString const& report_sent
, QString const& report_received, QString const& tx_power, QString const& comments
- , QString const& name, QDateTime time_on, QString const& operator_call);
+ , QString const& name, QDateTime time_on, QString const& operator_call
+ , QString const& my_call, QString const& my_grid);
Q_SIGNAL void clear_decodes (QString const& id);
+ Q_SIGNAL void logged_ADIF (QString const& id, QByteArray const& ADIF);
// this signal is emitted when a network error occurs
Q_SIGNAL void error (QString const&) const;
diff --git a/NetworkMessage.hpp b/NetworkMessage.hpp
index a14d6d1b8..479575a32 100644
--- a/NetworkMessage.hpp
+++ b/NetworkMessage.hpp
@@ -237,6 +237,9 @@
* Comments utf8
* Name utf8
* Date & Time On QDateTime
+ * Operator call utf8
+ * My call utf8
+ * My grid utf8
*
* The QSO logged message is sent to the server(s) when the
* WSJT-X user accepts the "Log QSO" dialog by clicking the "OK"
@@ -304,6 +307,7 @@
* command to determine the contents of the current free text
* message.
*
+ *
* WSPRDecode Out 10 quint32
* Id (unique key) utf8
* New bool
@@ -327,6 +331,43 @@
* from a played back recording.
*
*
+ * Location In 11
+ * Id (unique key) utf8
+ * Location utf8
+ *
+ * This message allows the server to set the current current
+ * geographical location of operation. The supplied location is
+ * not persistent but is used as a session lifetime replacement
+ * loction that overrides the Maidenhead grid locater set in the
+ * application settings. The intent is to allow an external
+ * application to update the operating location dynamically
+ * during a mobile period of operation.
+ *
+ * Currently only Maidenhead grid squares or sub-squares are
+ * accepted, i.e. 4- or 6-digit locators. Other formats may be
+ * accepted in future.
+ *
+ *
+ * Logged ADIF Out 12 quint32
+ * Id (unique key) utf8
+ * ADIF text ASCII (serialized like utf8)
+ *
+ * The logged ADIF message is sent to the server(s) when the
+ * WSJT-X user accepts the "Log QSO" dialog by clicking the "OK"
+ * button. The "ADIF text" field consists of a valid ADIF file
+ * such that the WSJT-X UDP header information is encapsulated
+ * into a valid ADIF header. E.g.:
+ *
+ * <32-bit-count> # binary encoded fields
+ * # the remainder is the contents of the ADIF text field
+ * 3.0.7
+ * WSJT-X
+ *
+ * ADIF log data fields ...
+ *
+ * Note that receiving applications can treat the whole message
+ * as a valid ADIF file with one record without special parsing.
+ *
*/
#include
@@ -353,6 +394,8 @@ namespace NetworkMessage
HaltTx,
FreeText,
WSPRDecode,
+ Location,
+ LoggedADIF,
maximum_message_type_ // ONLY add new message types
// immediately before here
};
diff --git a/UDPExamples/ClientWidget.cpp b/UDPExamples/ClientWidget.cpp
index de77286b8..001041cae 100644
--- a/UDPExamples/ClientWidget.cpp
+++ b/UDPExamples/ClientWidget.cpp
@@ -3,6 +3,8 @@
#include
#include
+#include "MaidenheadLocatorValidator.hpp"
+
namespace
{
//QRegExp message_alphabet {"[- A-Za-z0-9+./?]*"};
@@ -120,9 +122,11 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
, decodes_table_view_ {new QTableView}
, beacons_table_view_ {new QTableView}
, message_line_edit_ {new QLineEdit}
+ , grid_line_edit_ {new QLineEdit}
, decodes_stack_ {new QStackedLayout}
, auto_off_button_ {new QPushButton {tr ("&Auto Off")}}
, halt_tx_button_ {new QPushButton {tr ("&Halt Tx")}}
+ , de_label_ {new QLabel}
, mode_label_ {new QLabel}
, fast_mode_ {false}
, frequency_label_ {new QLabel}
@@ -141,13 +145,18 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
auto form_layout = new QFormLayout;
form_layout->addRow (tr ("Free text:"), message_line_edit_);
+ form_layout->addRow (tr ("Temporary grid:"), grid_line_edit_);
message_line_edit_->setValidator (new QRegExpValidator {message_alphabet, this});
+ grid_line_edit_->setValidator (new MaidenheadLocatorValidator {this});
connect (message_line_edit_, &QLineEdit::textEdited, [this] (QString const& text) {
Q_EMIT do_free_text (id_, text, false);
});
connect (message_line_edit_, &QLineEdit::editingFinished, [this] () {
Q_EMIT do_free_text (id_, message_line_edit_->text (), true);
});
+ connect (grid_line_edit_, &QLineEdit::editingFinished, [this] () {
+ Q_EMIT location (id_, grid_line_edit_->text ());
+ });
auto decodes_page = new QWidget;
auto decodes_layout = new QVBoxLayout {decodes_page};
@@ -189,6 +198,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
// set up status area
auto status_bar = new QStatusBar;
+ status_bar->addPermanentWidget (de_label_);
status_bar->addPermanentWidget (mode_label_);
status_bar->addPermanentWidget (frequency_label_);
status_bar->addPermanentWidget (dx_label_);
@@ -216,7 +226,7 @@ ClientWidget::ClientWidget (QAbstractItemModel * decodes_model, QAbstractItemMod
void ClientWidget::update_status (QString const& id, Frequency f, QString const& mode, QString const& dx_call
, QString const& report, QString const& tx_mode, bool tx_enabled
, bool transmitting, bool decoding, qint32 rx_df, qint32 tx_df
- , QString const& de_call, QString const& /*de_grid*/, QString const& dx_grid
+ , QString const& de_call, QString const& de_grid, QString const& dx_grid
, bool watchdog_timeout, QString const& sub_mode, bool fast_mode)
{
if (id == id_)
@@ -224,6 +234,8 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const&
fast_mode_ = fast_mode;
decodes_proxy_model_.de_call (de_call);
decodes_proxy_model_.rx_df (rx_df);
+ de_label_->setText (de_call.size () >= 0 ? QString {"DE: %1%2"}.arg (de_call)
+ .arg (de_grid.size () ? '(' + de_grid + ')' : QString {}) : QString {});
mode_label_->setText (QString {"Mode: %1%2%3%4"}
.arg (mode)
.arg (sub_mode)
diff --git a/UDPExamples/ClientWidget.hpp b/UDPExamples/ClientWidget.hpp
index 1f5ae6012..0cec23e7a 100644
--- a/UDPExamples/ClientWidget.hpp
+++ b/UDPExamples/ClientWidget.hpp
@@ -43,6 +43,7 @@ public:
Q_SIGNAL void do_reply (QModelIndex const&, quint8 modifier);
Q_SIGNAL void do_halt_tx (QString const& id, bool auto_only);
Q_SIGNAL void do_free_text (QString const& id, QString const& text, bool);
+ Q_SIGNAL void location (QString const &id, QString const &text);
private:
QString id_;
@@ -69,9 +70,11 @@ private:
QTableView * decodes_table_view_;
QTableView * beacons_table_view_;
QLineEdit * message_line_edit_;
+ QLineEdit * grid_line_edit_;
QStackedLayout * decodes_stack_;
QAbstractButton * auto_off_button_;
QAbstractButton * halt_tx_button_;
+ QLabel * de_label_;
QLabel * mode_label_;
bool fast_mode_;
QLabel * frequency_label_;
diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp
index 196282d61..324c7d0e5 100644
--- a/UDPExamples/MessageAggregatorMainWindow.cpp
+++ b/UDPExamples/MessageAggregatorMainWindow.cpp
@@ -22,12 +22,15 @@ namespace
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Sent"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Rec'd"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Power"),
+ QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Operator"),
+ QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "My Call"),
+ QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "My Grid"),
QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Comments"),
};
}
MessageAggregatorMainWindow::MessageAggregatorMainWindow ()
- : log_ {new QStandardItemModel {0, 11, this}}
+ : log_ {new QStandardItemModel {0, 14, this}}
, decodes_model_ {new DecodesModel {this}}
, beacons_model_ {new BeaconsModel {this}}
, server_ {new MessageServer {this}}
@@ -111,10 +114,12 @@ MessageAggregatorMainWindow::MessageAggregatorMainWindow ()
show ();
}
-void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time_off, QString const& dx_call, QString const& dx_grid
- , Frequency dial_frequency, QString const& mode, QString const& report_sent
- , QString const& report_received, QString const& tx_power, QString const& comments
- , QString const& name, QDateTime time_on)
+void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time_off, QString const& dx_call
+ , QString const& dx_grid, Frequency dial_frequency, QString const& mode
+ , QString const& report_sent, QString const& report_received
+ , QString const& tx_power, QString const& comments
+ , QString const& name, QDateTime time_on, QString const& operator_call
+ , QString const& my_call, QString const& my_grid)
{
QList row;
row << new QStandardItem {time_on.toString ("dd-MMM-yyyy hh:mm:ss")}
@@ -127,6 +132,9 @@ void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time
<< new QStandardItem {report_sent}
<< new QStandardItem {report_received}
<< new QStandardItem {tx_power}
+ << new QStandardItem {operator_call}
+ << new QStandardItem {my_call}
+ << new QStandardItem {my_grid}
<< new QStandardItem {comments};
log_->appendRow (row);
log_table_view_->resizeColumnsToContents ();
@@ -149,6 +157,7 @@ void MessageAggregatorMainWindow::add_client (QString const& id, QString const&
connect (dock, &ClientWidget::do_reply, decodes_model_, &DecodesModel::do_reply);
connect (dock, &ClientWidget::do_halt_tx, server_, &MessageServer::halt_tx);
connect (dock, &ClientWidget::do_free_text, server_, &MessageServer::free_text);
+ connect (dock, &ClientWidget::location, server_, &MessageServer::location);
connect (view_action, &QAction::toggled, dock, &ClientWidget::setVisible);
dock_widgets_[id] = dock;
server_->replay (id);
diff --git a/UDPExamples/MessageAggregatorMainWindow.hpp b/UDPExamples/MessageAggregatorMainWindow.hpp
index 4039c60ab..4ee5bface 100644
--- a/UDPExamples/MessageAggregatorMainWindow.hpp
+++ b/UDPExamples/MessageAggregatorMainWindow.hpp
@@ -29,7 +29,8 @@ public:
Q_SLOT void log_qso (QString const& /*id*/, QDateTime time_off, QString const& dx_call, QString const& dx_grid
, Frequency dial_frequency, QString const& mode, QString const& report_sent
, QString const& report_received, QString const& tx_power, QString const& comments
- , QString const& name, QDateTime time_on);
+ , QString const& name, QDateTime time_on, QString const& operator_call
+ , QString const& my_call, QString const& my_grid);
private:
void add_client (QString const& id, QString const& version, QString const& revision);
diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp
index 731f31661..b75a8adec 100644
--- a/UDPExamples/UDPDaemon.cpp
+++ b/UDPExamples/UDPDaemon.cpp
@@ -96,23 +96,37 @@ public:
}
Q_SLOT void qso_logged (QString const&client_id, QDateTime time_off, QString const& dx_call, QString const& dx_grid
- , Frequency dial_frequency, QString const& mode, QString const& report_sent
- , QString const& report_received, QString const& tx_power
- , QString const& comments, QString const& name, QDateTime time_on, QString const& operator_call)
+ , Frequency dial_frequency, QString const& mode, QString const& report_sent
+ , QString const& report_received, QString const& tx_power
+ , QString const& comments, QString const& name, QDateTime time_on
+ , QString const& operator_call, QString const& my_call, QString const& my_grid)
{
if (client_id == id_)
{
qDebug () << "time_on:" << time_on << "time_off:" << time_off << "dx_call:" << dx_call << "grid:" << dx_grid
<< "freq:" << dial_frequency << "mode:" << mode << "rpt_sent:" << report_sent
<< "rpt_rcvd:" << report_received << "Tx_pwr:" << tx_power << "comments:" << comments
- << "name:" << name << "operator_call:" << operator_call;
- std::cout << tr ("%1: Logged %2 grid: %3 power: %4 sent: %5 recd: %6 freq: %7 op: %8").arg (id_)
- .arg (dx_call).arg (dx_grid).arg (tx_power).arg (report_sent).arg (report_received).arg (dial_frequency).arg (operator_call).toStdString ()
- << tr (" @ %1").arg (time_off.toString("yyyy-MM-dd hh:mm:ss.z")).toStdString()
+ << "name:" << name << "operator_call:" << operator_call << "my_call:" << my_call
+ << "my_grid:" << my_grid;
+ std::cout << QByteArray {80, '-'}.data () << '\n';
+ std::cout << tr ("%1: Logged %2 grid: %3 power: %4 sent: %5 recd: %6 freq: %7 time_off: %8 op: %9 my_call: %10 my_grid: %11")
+ .arg (id_).arg (dx_call).arg (dx_grid).arg (tx_power).arg (report_sent).arg (report_received)
+ .arg (dial_frequency).arg (time_off.toString("yyyy-MM-dd hh:mm:ss.z")).arg (operator_call)
+ .arg (my_call).arg (my_grid).toStdString ()
<< std::endl;
}
}
+ Q_SLOT void logged_ADIF (QString const&client_id, QByteArray const& ADIF)
+ {
+ if (client_id == id_)
+ {
+ qDebug () << "ADIF:" << ADIF;
+ std::cout << QByteArray {80, '-'}.data () << '\n';
+ std::cout << ADIF.data () << std::endl;
+ }
+ }
+
private:
QString id_;
Frequency dial_frequency_;
@@ -146,6 +160,7 @@ private:
connect (server_, &MessageServer::decode, client, &Client::decode_added);
connect (server_, &MessageServer::WSPR_decode, client, &Client::beacon_spot_added);
connect (server_, &MessageServer::qso_logged, client, &Client::qso_logged);
+ connect (server_, &MessageServer::logged_ADIF, client, &Client::logged_ADIF);
clients_[id] = client;
server_->replay (id);
std::cout << "Discovered WSJT-X instance: " << id.toStdString ();
diff --git a/logbook/adif.cpp b/logbook/adif.cpp
index 31cd39a9d..568a2eb1c 100644
--- a/logbook/adif.cpp
+++ b/logbook/adif.cpp
@@ -174,8 +174,11 @@ int ADIF::getCount() const
return _data.size();
}
-QString ADIF::QSOToADIF(QString const& hisCall, QString const& hisGrid, QString const& mode, QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn, QDateTime const& dateTimeOff, QString const& band,
- QString const& comments, QString const& name, QString const& strDialFreq, QString const& m_myCall, QString const& m_myGrid, QString const& m_txPower, QString const& operator_call)
+QByteArray ADIF::QSOToADIF(QString const& hisCall, QString const& hisGrid, QString const& mode
+ , QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn
+ , QDateTime const& dateTimeOff, QString const& band, QString const& comments
+ , QString const& name, QString const& strDialFreq, QString const& m_myCall
+ , QString const& m_myGrid, QString const& m_txPower, QString const& operator_call)
{
QString t;
t = "" + hisCall;
@@ -205,14 +208,12 @@ QString ADIF::QSOToADIF(QString const& hisCall, QString const& hisGrid, QString
if (operator_call!="")
t+=" " + operator_call;
- t += " ";
- return t;
+ return t.toLatin1 ();
}
// open ADIF file and append the QSO details. Return true on success
-bool ADIF::addQSOToFile(QString const& hisCall, QString const& hisGrid, QString const& mode, QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn, QDateTime const& dateTimeOff, QString const& band,
- QString const& comments, QString const& name, QString const& strDialFreq, QString const& m_myCall, QString const& m_myGrid, QString const& m_txPower, QString const& operator_call)
+bool ADIF::addQSOToFile(QByteArray const& ADIF_record)
{
QFile f2(_filename);
if (!f2.open(QIODevice::Text | QIODevice::Append))
@@ -223,10 +224,7 @@ bool ADIF::addQSOToFile(QString const& hisCall, QString const& hisGrid, QString
if (f2.size()==0)
out << "WSJT-X ADIF Export" << endl; // new file
- QString t;
- t = QSOToADIF(hisCall,hisGrid,mode,rptSent,rptRcvd,dateTimeOn,dateTimeOff,
- band,comments,name,strDialFreq,m_myCall,m_myGrid,m_txPower,operator_call);
- out << t << endl;
+ out << ADIF_record << " " << endl;
f2.close();
}
return true;
diff --git a/logbook/adif.h b/logbook/adif.h
index 2c82c2144..727ca9952 100644
--- a/logbook/adif.h
+++ b/logbook/adif.h
@@ -29,11 +29,13 @@ class ADIF
int getCount() const;
// open ADIF file and append the QSO details. Return true on success
- bool addQSOToFile(QString const& hisCall, QString const& hisGrid, QString const& mode, QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn, QDateTime const& dateTimeOff, QString const& band,
- QString const& comments, QString const& name, QString const& strDialFreq, QString const& m_myCall, QString const& m_myGrid, QString const& m_txPower, QString const& operator_call);
+ bool addQSOToFile(QByteArray const& ADIF_record);
- QString QSOToADIF(QString const& hisCall, QString const& hisGrid, QString const& mode, QString const& rptSent, QString const& rptRcvd, QDateTime const& dateTimeOn, QDateTime const& dateTimeOff, QString const& band,
- QString const& comments, QString const& name, QString const& strDialFreq, QString const& m_myCall, QString const& m_myGrid, QString const& m_txPower, QString const& operator_call);
+ QByteArray QSOToADIF(QString const& hisCall, QString const& hisGrid, QString const& mode, QString const& rptSent
+ , QString const& rptRcvd, QDateTime const& dateTimeOn, QDateTime const& dateTimeOff
+ , QString const& band, QString const& comments, QString const& name
+ , QString const& strDialFreq, QString const& m_myCall, QString const& m_myGrid
+ , QString const& m_txPower, QString const& operator_call);
private:
diff --git a/logqso.cpp b/logqso.cpp
index c0c7572d6..3fa454c6a 100644
--- a/logqso.cpp
+++ b/logqso.cpp
@@ -117,7 +117,9 @@ void LogQSO::accept()
auto adifilePath = QDir {QStandardPaths::writableLocation (QStandardPaths::DataLocation)}.absoluteFilePath ("wsjtx_log.adi");
adifile.init(adifilePath);
- if (!adifile.addQSOToFile(hisCall,hisGrid,mode,rptSent,rptRcvd,m_dateTimeOn,m_dateTimeOff,band,comments,name,strDialFreq,m_myCall,m_myGrid,m_txPower, operator_call))
+ QByteArray ADIF {adifile.QSOToADIF (hisCall, hisGrid, mode, rptSent, rptRcvd, m_dateTimeOn, m_dateTimeOff, band
+ , comments, name, strDialFreq, m_myCall, m_myGrid, m_txPower, operator_call)};
+ if (!adifile.addQSOToFile (ADIF))
{
MessageBox::warning_message (this, tr ("Log file error"),
tr ("Cannot open \"%1\"").arg (adifilePath));
@@ -125,12 +127,9 @@ void LogQSO::accept()
// Log to N1MM Logger
if (m_config->broadcast_to_n1mm() && m_config->valid_n1mm_info()) {
- QString adif = adifile.QSOToADIF(hisCall,hisGrid,mode,rptSent,rptRcvd,m_dateTimeOn,m_dateTimeOff,band,comments,name,strDialFreq,m_myCall,m_myGrid,m_txPower, operator_call);
const QHostAddress n1mmhost = QHostAddress(m_config->n1mm_server_name());
- QByteArray qba_adif = adif.toLatin1();
QUdpSocket _sock;
-
- auto rzult = _sock.writeDatagram ( qba_adif, n1mmhost, quint16(m_config->n1mm_server_port()));
+ auto rzult = _sock.writeDatagram (ADIF + " ", n1mmhost, quint16(m_config->n1mm_server_port()));
if (rzult == -1) {
MessageBox::warning_message (this, tr ("Error sending log to N1MM"),
tr ("Write returned \"%1\"").arg (rzult));
@@ -157,7 +156,7 @@ void LogQSO::accept()
}
//Clean up and finish logging
- Q_EMIT acceptQSO (m_dateTimeOff, hisCall, hisGrid, m_dialFreq, mode, rptSent, rptRcvd, m_txPower, comments, name,m_dateTimeOn, operator_call);
+ Q_EMIT acceptQSO (m_dateTimeOff, hisCall, hisGrid, m_dialFreq, mode, rptSent, rptRcvd, m_txPower, comments, name,m_dateTimeOn, operator_call, m_myCall, m_myGrid, ADIF);
QDialog::accept();
}
diff --git a/logqso.h b/logqso.h
index 4f22649b8..fb92201e1 100644
--- a/logqso.h
+++ b/logqso.h
@@ -8,7 +8,9 @@
#include
#endif
+#include
#include
+#include
#include "Radio.hpp"
@@ -18,6 +20,7 @@ namespace Ui {
class QSettings;
class Configuration;
+class QByteArray;
class LogQSO : public QDialog
{
@@ -40,7 +43,8 @@ signals:
, Radio::Frequency dial_freq, QString const& mode
, QString const& rpt_sent, QString const& rpt_received
, QString const& tx_power, QString const& comments
- , QString const& name, QDateTime const& QSO_date_on, QString const& operator_call);
+ , QString const& name, QDateTime const& QSO_date_on, QString const& operator_call
+ , QString const& my_call, QString const& my_grid, QByteArray const& ADIF);
protected:
void hideEvent (QHideEvent *);
diff --git a/mainwindow.cpp b/mainwindow.cpp
index f2182b3af..556bc8be5 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -446,12 +446,13 @@ MainWindow::MainWindow(QDir const& temp_directory, bool multiple,
connect (this, &MainWindow::finished, m_fastGraph.data (), &FastGraph::close);
// setup the log QSO dialog
- connect (m_logDlg.data (), &LogQSO::acceptQSO, this, &MainWindow::acceptQSO2);
+ connect (m_logDlg.data (), &LogQSO::acceptQSO, this, &MainWindow::acceptQSO);
connect (this, &MainWindow::finished, m_logDlg.data (), &LogQSO::close);
// Network message handlers
connect (m_messageClient, &MessageClient::reply, this, &MainWindow::replyToCQ);
connect (m_messageClient, &MessageClient::replay, this, &MainWindow::replayDecodes);
+ connect (m_messageClient, &MessageClient::location, this, &MainWindow::locationChange);
connect (m_messageClient, &MessageClient::halt_tx, [this] (bool auto_only) {
if (m_config.accept_udp_requests ()) {
if (auto_only) {
@@ -1581,13 +1582,16 @@ void MainWindow::on_actionSettings_triggered() //Setup Dialog
{
// things that might change that we need know about
auto callsign = m_config.my_callsign ();
+ auto my_grid = m_config.my_grid ();
if (QDialog::Accepted == m_config.exec ()) {
if (m_config.my_callsign () != callsign) {
m_baseCall = Radio::base_callsign (m_config.my_callsign ());
morse_(const_cast (m_config.my_callsign ().toLatin1().constData()),
const_cast (icw), &m_ncw, m_config.my_callsign ().length());
}
-
+ if (m_config.my_callsign () != callsign || m_config.my_grid () != my_grid) {
+ statusUpdate ();
+ }
on_dxGridEntry_textChanged (m_hisGrid); // recalculate distances in case of units change
enable_DXCC_entity (m_config.DXCC ()); // sets text window proportions and (re)inits the logbook
@@ -4811,16 +4815,18 @@ void MainWindow::on_logQSOButton_clicked() //Log QSO button
m_config.bFox(), m_opCall);
}
-void MainWindow::acceptQSO2(QDateTime const& QSO_date_off, QString const& call, QString const& grid
+void MainWindow::acceptQSO (QDateTime const& QSO_date_off, QString const& call, QString const& grid
, Frequency dial_freq, QString const& mode
, QString const& rpt_sent, QString const& rpt_received
, QString const& tx_power, QString const& comments
- , QString const& name, QDateTime const& QSO_date_on, QString const& operator_call)
+ , QString const& name, QDateTime const& QSO_date_on, QString const& operator_call
+ , QString const& my_call, QString const& my_grid, QByteArray const& ADIF)
{
QString date = QSO_date_on.toString("yyyyMMdd");
m_logBook.addAsWorked (m_hisCall, m_config.bands ()->find (m_freqNominal), m_modeTx, date);
- m_messageClient->qso_logged (QSO_date_off, call, grid, dial_freq, mode, rpt_sent, rpt_received, tx_power, comments, name, QSO_date_on, operator_call);
+ m_messageClient->qso_logged (QSO_date_off, call, grid, dial_freq, mode, rpt_sent, rpt_received, tx_power, comments, name, QSO_date_on, operator_call, my_call, my_grid);
+ m_messageClient->logged_ADIF (ADIF);
if (m_config.clear_DX ())
{
@@ -6522,6 +6528,33 @@ void MainWindow::replyToCQ (QTime time, qint32 snr, float delta_time, quint32 de
}
}
+void MainWindow::locationChange (QString const& location)
+{
+ QString grid {location.trimmed ()};
+ int len;
+
+ // string 6 chars or fewer, interpret as a grid, or use with a 'GRID:' prefix
+ if (grid.size () > 6) {
+ if (grid.toUpper ().startsWith ("GRID:")) {
+ grid = grid.mid (5).trimmed ();
+ }
+ else {
+ // TODO - support any other formats, e.g. latlong? Or have that conversion done external to wsjtx
+ return;
+ }
+ }
+ if (MaidenheadLocatorValidator::Acceptable == MaidenheadLocatorValidator ().validate (grid, len)) {
+ qDebug() << "locationChange: Grid supplied is " << grid;
+ if (m_config.my_grid () != grid) {
+ m_config.set_location (grid);
+ genStdMsgs (m_rpt, false);
+ statusUpdate ();
+ }
+ } else {
+ qDebug() << "locationChange: Invalid grid " << grid;
+ }
+}
+
void MainWindow::replayDecodes ()
{
// we accept this request even if the setting to accept UDP requests
diff --git a/mainwindow.h b/mainwindow.h
index 5f48e9891..5e912a097 100644
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -218,11 +218,12 @@ private slots:
void on_tuneButton_clicked (bool);
void on_pbR2T_clicked();
void on_pbT2R_clicked();
- void acceptQSO2(QDateTime const&, QString const& call, QString const& grid
+ void acceptQSO (QDateTime const&, QString const& call, QString const& grid
, Frequency dial_freq, QString const& mode
, QString const& rpt_sent, QString const& rpt_received
, QString const& tx_power, QString const& comments
- , QString const& name, QDateTime const& QSO_date_on, QString const& operator_call);
+ , QString const& name, QDateTime const& QSO_date_on, QString const& operator_call
+ , QString const& my_call, QString const& my_grid, QByteArray const& ADIF);
void on_bandComboBox_currentIndexChanged (int index);
void on_bandComboBox_activated (int index);
void on_readFreq_clicked();
@@ -645,6 +646,7 @@ private:
void transmitDisplay (bool);
void processMessage(DecodedText const&, Qt::KeyboardModifiers = 0);
void replyToCQ (QTime, qint32 snr, float delta_time, quint32 delta_frequency, QString const& mode, QString const& message_text, bool low_confidence, quint8 modifiers);
+ void locationChange(QString const& location);
void replayDecodes ();
void postDecode (bool is_new, QString const& message);
void postWSPRDecode (bool is_new, QStringList message_parts);