diff --git a/Configuration.cpp b/Configuration.cpp index 244d885a2..c0c9a982f 100644 --- a/Configuration.cpp +++ b/Configuration.cpp @@ -210,6 +210,7 @@ namespace |DX # anyone else ) )", QRegularExpression::CaseInsensitiveOption | QRegularExpression::ExtendedPatternSyntaxOption}; + QRegularExpression field_day_exchange_re { R"( ( @@ -217,7 +218,7 @@ namespace |[0-2]\d |3[0-2] ) - [A-F]\ # class and space + [A-F]\ * # class and optional space ( AB|AK|AL|AR|AZ|BC|CO|CT|DE|EB # ARRL/RAC section |EMA|ENY|EPA|EWA|GA|GTA|IA|ID @@ -488,6 +489,8 @@ private: Q_SLOT void on_cbx4ToneSpacing_clicked(bool); Q_SLOT void on_prompt_to_log_check_box_clicked(bool); Q_SLOT void on_cbAutoLog_clicked(bool); + Q_SLOT void on_Field_Day_Exchange_textEdited (QString const&); + Q_SLOT void on_RTTY_Exchange_textEdited (QString const&); // typenames used as arguments must match registered type names :( Q_SIGNAL void start_transceiver (unsigned seqeunce_number) const; @@ -1011,8 +1014,8 @@ Configuration::impl::impl (Configuration * self, QNetworkAccessManager * network ui_->callsign_line_edit->setValidator (new CallsignValidator {this}); ui_->grid_line_edit->setValidator (new MaidenheadLocatorValidator {this}); ui_->add_macro_line_edit->setValidator (new QRegularExpressionValidator {message_alphabet, this}); - ui_->Field_Day_Exchange->setValidator(new QRegularExpressionValidator {field_day_exchange_re}); - ui_->RTTY_Exchange->setValidator(new QRegularExpressionValidator {RTTY_roundup_exchange_re}); + ui_->Field_Day_Exchange->setValidator (new QRegularExpressionValidator {field_day_exchange_re, this}); + ui_->RTTY_Exchange->setValidator (new QRegularExpressionValidator {RTTY_roundup_exchange_re, this}); ui_->udp_server_port_spin_box->setMinimum (1); ui_->udp_server_port_spin_box->setMaximum (std::numeric_limits::max ()); @@ -2507,6 +2510,22 @@ void Configuration::impl::on_cbx4ToneSpacing_clicked(bool b) if(b) ui_->cbx2ToneSpacing->setChecked(false); } +void Configuration::impl::on_Field_Day_Exchange_textEdited (QString const& exchange) +{ + auto text = exchange.simplified ().toUpper (); + auto class_pos = text.indexOf (QRegularExpression {R"([A-H])"}); + if (class_pos >= 0 && text.size () >= class_pos + 2 && text.at (class_pos + 1) != QChar {' '}) + { + text.insert (class_pos + 1, QChar {' '}); + } + ui_->Field_Day_Exchange->setText (text); +} + +void Configuration::impl::on_RTTY_Exchange_textEdited (QString const& exchange) +{ + ui_->RTTY_Exchange->setText (exchange.toUpper ()); +} + bool Configuration::impl::have_rig () { if (!open_rig ()) diff --git a/Configuration.ui b/Configuration.ui index f52eeb2be..6b04fd353 100644 --- a/Configuration.ui +++ b/Configuration.ui @@ -16,9 +16,6 @@ - - Select tab to change configuration parameters. - 0 @@ -2259,6 +2256,9 @@ Right click for insert and delete options. + + <html><head/><body><p>Click to scan the wsjtx_log.adi ADIF file again for worked before information</p></body></html> + Rescan ADIF Log @@ -2456,7 +2456,140 @@ Right click for insert and delete options. false - + + + + + <html><head/><body><p>FT8 DXpedition mode: Hound operator calling the DX.</p></body></html> + + + Hound + + + true + + + special_op_activity_button_group + + + + + + + + 0 + 0 + + + + <html><head/><body><p>North American VHF/UHF/Microwave contests and others in which a 4-character grid locator is the required exchange.</p></body></html> + + + NA VHF Contest + + + special_op_activity_button_group + + + + + + + <html><head/><body><p>FT8 DXpedition mode: Fox (DXpedition) operator.</p></body></html> + + + Fox + + + false + + + special_op_activity_button_group + + + + + + + + 0 + 0 + + + + <html><head/><body><p>European VHF+ contests requiring a signal report, serial number, and 6-character locator.</p></body></html> + + + EU VHF Contest + + + special_op_activity_button_group + + + + + + + + + <html><head/><body><p>ARRL RTTY Roundup and similar contests. Exchange is US state, Canadian province, or &quot;DX&quot;.</p></body></html> + + + ARRL RTTY Roundup + + + special_op_activity_button_group + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + RTTY RU Exch: + + + RTTY_Exchange + + + + + + + + 70 + 0 + + + + <html><head/><body><p>ARRL RTTY Roundup and similar contests. Exchange is US state, Canadian province, or &quot;DX&quot;.</p></body></html> + + + NJ + + + Qt::AlignCenter + + + + + + + @@ -2503,7 +2636,7 @@ Right click for insert and delete options. - Exch: + FD Exch: Field_Day_Exchange @@ -2533,152 +2666,6 @@ Right click for insert and delete options. - - - - - - <html><head/><body><p>ARRL RTTY Roundup and similar contests. Exchange is US state, Canadian province, or &quot;DX&quot;.</p></body></html> - - - ARRL RTTY Roundup - - - special_op_activity_button_group - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Exch: - - - RTTY_Exchange - - - - - - - - 70 - 0 - - - - <html><head/><body><p>ARRL RTTY Roundup and similar contests. Exchange is US state, Canadian province, or &quot;DX&quot;.</p></body></html> - - - NJ - - - Qt::AlignCenter - - - - - - - - - - - <html><head/><body><p>FT8 DXpedition mode: Fox (DXpedition) operator.</p></body></html> - - - Fox - - - false - - - special_op_activity_button_group - - - - - - - - 0 - 0 - - - - <html><head/><body><p>European VHF+ contests requiring a signal report, serial number, and 6-character locator.</p></body></html> - - - EU VHF Contest - - - special_op_activity_button_group - - - - - - - - 0 - 0 - - - - <html><head/><body><p>North American VHF/UHF/Microwave contests and others in which a 4-character grid locator is the required exchange.</p></body></html> - - - NA VHF Contest - - - special_op_activity_button_group - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - <html><head/><body><p>FT8 DXpedition mode: Hound operator calling the DX.</p></body></html> - - - Hound - - - true - - - special_op_activity_button_group - - - @@ -3031,13 +3018,13 @@ Right click for insert and delete options. - - - + - + + + diff --git a/MessageClient.cpp b/MessageClient.cpp index 80ceb04e6..6ceca2dce 100644 --- a/MessageClient.cpp +++ b/MessageClient.cpp @@ -405,7 +405,7 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con , qint32 rx_df, qint32 tx_df, QString const& de_call , QString const& de_grid, QString const& dx_grid , bool watchdog_timeout, QString const& sub_mode - , bool fast_mode) + , bool fast_mode, quint8 special_op_mode) { if (m_->server_port_ && !m_->server_string_.isEmpty ()) { @@ -414,7 +414,7 @@ void MessageClient::status_update (Frequency f, QString const& mode, QString con out << f << mode.toUtf8 () << dx_call.toUtf8 () << report.toUtf8 () << tx_mode.toUtf8 () << tx_enabled << transmitting << decoding << rx_df << tx_df << de_call.toUtf8 () << de_grid.toUtf8 () << dx_grid.toUtf8 () << watchdog_timeout << sub_mode.toUtf8 () - << fast_mode; + << fast_mode << special_op_mode; m_->send_message (out, message); } } @@ -462,7 +462,8 @@ void MessageClient::qso_logged (QDateTime time_off, QString const& dx_call, QStr , 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) + , QString const& my_grid, QString const& exchange_sent + , QString const& exchange_rcvd) { if (m_->server_port_ && !m_->server_string_.isEmpty ()) { @@ -470,7 +471,8 @@ 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 () << my_call.toUtf8 () << my_grid.toUtf8 (); + << name.toUtf8 () << time_on << operator_call.toUtf8 () << my_call.toUtf8 () << my_grid.toUtf8 () + << exchange_sent.toUtf8 () << exchange_rcvd.toUtf8 (); m_->send_message (out, message); } } diff --git a/MessageClient.hpp b/MessageClient.hpp index e1208f9c8..0deb1a49d 100644 --- a/MessageClient.hpp +++ b/MessageClient.hpp @@ -52,7 +52,7 @@ public: , 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, bool watchdog_timeout, QString const& sub_mode - , bool fast_mode); + , bool fast_mode, quint8 special_op_mode); Q_SLOT void decode (bool is_new, QTime time, qint32 snr, float delta_time, quint32 delta_frequency , QString const& mode, QString const& message, bool low_confidence , bool off_air); @@ -64,7 +64,8 @@ public: , 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); + , QString const& my_call, QString const& my_grid + , QString const& exchange_sent, QString const& exchange_rcvd); // ADIF_record argument should be valid ADIF excluding any end // of record marker diff --git a/MessageServer.cpp b/MessageServer.cpp index b5a719e74..609d24a9a 100644 --- a/MessageServer.cpp +++ b/MessageServer.cpp @@ -216,9 +216,10 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s bool watchdog_timeout {false}; QByteArray sub_mode; bool fast_mode {false}; + quint8 special_op_mode {0}; in >> f >> mode >> dx_call >> report >> tx_mode >> tx_enabled >> transmitting >> decoding >> rx_df >> tx_df >> de_call >> de_grid >> dx_grid >> watchdog_timeout >> sub_mode - >> fast_mode; + >> fast_mode >> special_op_mode; if (check_status (in) != Fail) { Q_EMIT self_->status_update (id, f, QString::fromUtf8 (mode), QString::fromUtf8 (dx_call) @@ -226,7 +227,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s , tx_enabled, transmitting, decoding, rx_df, tx_df , QString::fromUtf8 (de_call), QString::fromUtf8 (de_grid) , QString::fromUtf8 (dx_grid), watchdog_timeout - , QString::fromUtf8 (sub_mode), fast_mode); + , QString::fromUtf8 (sub_mode), fast_mode + , special_op_mode); } } break; @@ -294,8 +296,11 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s QByteArray operator_call; QByteArray my_call; QByteArray my_grid; + QByteArray exchange_sent; + QByteArray exchange_rcvd; in >> time_off >> dx_call >> dx_grid >> dial_frequency >> mode >> report_sent >> report_received - >> tx_power >> comments >> name >> time_on >> operator_call >> my_call >> my_grid; + >> tx_power >> comments >> name >> time_on >> operator_call >> my_call >> my_grid + >> exchange_sent >> exchange_rcvd; if (check_status (in) != Fail) { Q_EMIT self_->qso_logged (id, time_off, QString::fromUtf8 (dx_call), QString::fromUtf8 (dx_grid) @@ -303,7 +308,8 @@ void MessageServer::impl::parse_message (QHostAddress const& sender, port_type s , QString::fromUtf8 (report_received), QString::fromUtf8 (tx_power) , QString::fromUtf8 (comments), QString::fromUtf8 (name), time_on , QString::fromUtf8 (operator_call), QString::fromUtf8 (my_call) - , QString::fromUtf8 (my_grid)); + , QString::fromUtf8 (my_grid), QString::fromUtf8 (exchange_sent) + , QString::fromUtf8 (exchange_rcvd)); } } break; diff --git a/MessageServer.hpp b/MessageServer.hpp index bb7501529..4a6022bfd 100644 --- a/MessageServer.hpp +++ b/MessageServer.hpp @@ -76,7 +76,8 @@ public: , 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 - , bool watchdog_timeout, QString const& sub_mode, bool fast_mode); + , bool watchdog_timeout, QString const& sub_mode, bool fast_mode + , quint8 special_op_mode); Q_SIGNAL void client_closed (QString const& id); Q_SIGNAL void decode (bool is_new, QString const& id, QTime time, qint32 snr, float delta_time , quint32 delta_frequency, QString const& mode, QString const& message @@ -88,7 +89,8 @@ public: , 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); + , QString const& my_call, QString const& my_grid + , QString const& exchange_sent, QString const& exchange_rcvd); Q_SIGNAL void clear_decodes (QString const& id); Q_SIGNAL void logged_ADIF (QString const& id, QByteArray const& ADIF); diff --git a/NetworkMessage.hpp b/NetworkMessage.hpp index ffd0ff288..a4d9ba0d5 100644 --- a/NetworkMessage.hpp +++ b/NetworkMessage.hpp @@ -124,6 +124,7 @@ * Tx Watchdog bool * Sub-mode utf8 * Fast mode bool + * Special operation mode quint8 * * WSJT-X sends this status message when various internal state * changes to allow the server to track the relevant state of each @@ -142,10 +143,22 @@ * At the start and end of decoding, * When the Rx DF changes, * When the Tx DF changes, - * When the DE call or grid changes (currently when settings are exited), + * When settings are exited, * When the DX call or grid changes, * When the Tx watchdog is set or reset. * + * The Special operation mode is an enumeration that indicates the + * setting selected in the WSJT-X "Settings->Advanced->Special + * operating activity" panel. The values are as follows: + * + * 0 -> NONE + * 1 -> NA VHF + * 2 -> EU VHF + * 3 -> FIELD DAY + * 4 -> RTTY RU + * 5 -> FOX + * 6 -> HOUND + * * * Decode Out 2 quint32 * Id (unique key) utf8 @@ -240,6 +253,8 @@ * Operator call utf8 * My call utf8 * My grid utf8 + * Exchange sent utf8 + * Exchange received 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" diff --git a/UDPExamples/BeaconsModel.cpp b/UDPExamples/BeaconsModel.cpp index 1302dc05e..8955ea26a 100644 --- a/UDPExamples/BeaconsModel.cpp +++ b/UDPExamples/BeaconsModel.cpp @@ -72,7 +72,7 @@ namespace } BeaconsModel::BeaconsModel (QObject * parent) - : QStandardItemModel {0, sizeof (headings) / sizeof (headings[0]), parent} + : QStandardItemModel {0, sizeof headings / sizeof headings[0], parent} { int column {0}; for (auto const& heading : headings) diff --git a/UDPExamples/ClientWidget.cpp b/UDPExamples/ClientWidget.cpp index 10361d55d..7423f6d81 100644 --- a/UDPExamples/ClientWidget.cpp +++ b/UDPExamples/ClientWidget.cpp @@ -244,15 +244,29 @@ void ClientWidget::update_status (QString const& id, Frequency f, QString const& , 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 - , bool watchdog_timeout, QString const& sub_mode, bool fast_mode) + , bool watchdog_timeout, QString const& sub_mode, bool fast_mode + , quint8 special_op_mode) { if (id == id_) { 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 {}); + QString special; + switch (special_op_mode) + { + case 1: special = "[NA VHF]"; break; + case 2: special = "[EU VHF]"; break; + case 3: special = "[FD]"; break; + case 4: special = "[RTTY RU]"; break; + case 5: special = "[Fox]"; break; + case 6: special = "[Hound]"; break; + default: break; + } + de_label_->setText (de_call.size () >= 0 ? QString {"DE: %1%2%3"}.arg (de_call) + .arg (de_grid.size () ? '(' + de_grid + ')' : QString {}) + .arg (special) + : 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 29059bfa5..0459ad036 100644 --- a/UDPExamples/ClientWidget.hpp +++ b/UDPExamples/ClientWidget.hpp @@ -32,7 +32,8 @@ public: , 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 - , bool watchdog_timeout, QString const& sub_mode, bool fast_mode); + , bool watchdog_timeout, QString const& sub_mode, bool fast_mode + , quint8 special_op_mode); Q_SLOT void decode_added (bool is_new, QString const& client_id, QTime, qint32 snr , float delta_time, quint32 delta_frequency, QString const& mode , QString const& message, bool low_confidence, bool off_air); diff --git a/UDPExamples/DecodesModel.cpp b/UDPExamples/DecodesModel.cpp index 5847e49ff..88b071c11 100644 --- a/UDPExamples/DecodesModel.cpp +++ b/UDPExamples/DecodesModel.cpp @@ -75,7 +75,7 @@ namespace } DecodesModel::DecodesModel (QObject * parent) - : QStandardItemModel {0, sizeof (headings) / sizeof (headings[0]), parent} + : QStandardItemModel {0, sizeof headings / sizeof headings[0], parent} { int column {0}; for (auto const& heading : headings) diff --git a/UDPExamples/MessageAggregatorMainWindow.cpp b/UDPExamples/MessageAggregatorMainWindow.cpp index 1d1dce5d6..0c2c51c30 100644 --- a/UDPExamples/MessageAggregatorMainWindow.cpp +++ b/UDPExamples/MessageAggregatorMainWindow.cpp @@ -25,12 +25,14 @@ namespace QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Operator"), QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "My Call"), QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "My Grid"), + QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Exchange Sent"), + QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Exchange Rcvd"), QT_TRANSLATE_NOOP ("MessageAggregatorMainWindow", "Comments"), }; } MessageAggregatorMainWindow::MessageAggregatorMainWindow () - : log_ {new QStandardItemModel {0, 14, this}} + : log_ {new QStandardItemModel {0, sizeof headings / sizeof headings[0], this}} , decodes_model_ {new DecodesModel {this}} , beacons_model_ {new BeaconsModel {this}} , server_ {new MessageServer {this}} @@ -209,7 +211,8 @@ void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time , 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) + , QString const& my_call, QString const& my_grid + , QString const& exchange_sent, QString const& exchange_rcvd) { QList row; row << new QStandardItem {time_on.toString ("dd-MMM-yyyy hh:mm:ss")} @@ -225,6 +228,8 @@ void MessageAggregatorMainWindow::log_qso (QString const& /*id*/, QDateTime time << new QStandardItem {operator_call} << new QStandardItem {my_call} << new QStandardItem {my_grid} + << new QStandardItem {exchange_sent} + << new QStandardItem {exchange_rcvd} << new QStandardItem {comments}; log_->appendRow (row); log_table_view_->resizeColumnsToContents (); diff --git a/UDPExamples/MessageAggregatorMainWindow.hpp b/UDPExamples/MessageAggregatorMainWindow.hpp index b699bee93..29f762d3d 100644 --- a/UDPExamples/MessageAggregatorMainWindow.hpp +++ b/UDPExamples/MessageAggregatorMainWindow.hpp @@ -32,7 +32,8 @@ public: , 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); + , QString const& my_call, QString const& my_grid + , QString const& exchange_sent, QString const& exchange_rcvd); private: void add_client (QString const& id, QString const& version, QString const& revision); diff --git a/UDPExamples/UDPDaemon.cpp b/UDPExamples/UDPDaemon.cpp index b75a8adec..0ee202dc7 100644 --- a/UDPExamples/UDPDaemon.cpp +++ b/UDPExamples/UDPDaemon.cpp @@ -50,7 +50,8 @@ public: , 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*/ - , bool /* watchdog_timeout */, QString const& sub_mode, bool /*fast_mode*/) + , bool /* watchdog_timeout */, QString const& sub_mode, bool /*fast_mode*/ + , quint8 /*special_op_mode*/) { if (id == id_) { @@ -99,7 +100,8 @@ public: , 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) + , QString const& operator_call, QString const& my_call, QString const& my_grid + , QString const& exchange_sent, QString const& exchange_rcvd) { if (client_id == id_) { @@ -107,7 +109,8 @@ public: << "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 << "my_call:" << my_call - << "my_grid:" << my_grid; + << "my_grid:" << my_grid << "exchange_sent:" << exchange_sent + << "exchange_rcvd:" << exchange_rcvd; 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) diff --git a/item_delegates/DateTimeAsSecsSinceEpochDelegate.hpp b/item_delegates/DateTimeAsSecsSinceEpochDelegate.hpp index 5b7f76eb8..a666ed323 100644 --- a/item_delegates/DateTimeAsSecsSinceEpochDelegate.hpp +++ b/item_delegates/DateTimeAsSecsSinceEpochDelegate.hpp @@ -1,8 +1,10 @@ #ifndef DATE_TIME_AS_SECS_SINCE_EPOCH_DELEGATE_HPP_ #define DATE_TIME_AS_SECS_SINCE_EPOCH_DELEGATE_HPP_ +#include #include #include +#include #include #include #include @@ -33,12 +35,17 @@ public: QString displayText (QVariant const& value, QLocale const& locale) const override { - return locale.toString (to_date_time (value), QLocale::ShortFormat); + return locale.toString (to_date_time (value), locale.dateFormat (QLocale::ShortFormat) + " hh:mm:ss"); } QWidget * createEditor (QWidget * parent, QStyleOptionViewItem const& /*option*/, QModelIndex const& /*index*/) const override { - return new QDateTimeEdit {parent}; + std::unique_ptr editor {new QDateTimeEdit {parent}}; + editor->setDisplayFormat (parent->locale ().dateFormat (QLocale::ShortFormat) + " hh:mm:ss"); + editor->setTimeSpec (Qt::UTC); // needed because it ignores time + // spec of the QDateTime that it is + // set from + return editor.release (); } void setEditorData (QWidget * editor, QModelIndex const& index) const override diff --git a/models/CabrilloLog.cpp b/models/CabrilloLog.cpp index 965d6f957..d558e66e0 100644 --- a/models/CabrilloLog.cpp +++ b/models/CabrilloLog.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include "Configuration.hpp" #include "Bands.hpp" #include "qt_db_helpers.hpp" @@ -52,7 +51,7 @@ CabrilloLog::impl::impl (Configuration const * configuration) SQL_error_check (export_query_, &QSqlQuery::prepare, "SELECT frequency, \"when\", exchange_sent, call, exchange_rcvd FROM cabrillo_log ORDER BY \"when\""); - setEditStrategy (QSqlTableModel::OnRowChange); + setEditStrategy (QSqlTableModel::OnFieldChange); setTable ("cabrillo_log"); setHeaderData (fieldIndex ("frequency"), Qt::Horizontal, tr ("Freq(kHz)")); setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)")); @@ -110,6 +109,10 @@ bool CabrilloLog::add_QSO (Frequency frequency, QDateTime const& when, QString c set_value_maybe_null (record, "exchange_sent", exchange_sent); set_value_maybe_null (record, "exchange_rcvd", exchange_received); set_value_maybe_null (record, "band", m_->configuration_->bands ()->find (frequency)); + if (m_->isDirty ()) + { + m_->revert (); // discard any uncommitted changes + } auto ok = m_->insertRecord (-1, record); if (ok) { @@ -136,7 +139,7 @@ void CabrilloLog::reset () SQL_error_check (*m_, &QSqlTableModel::removeRows, 0, m_->rowCount (), QModelIndex {}); transaction.submit (); m_->select (); // to refresh views - m_->setEditStrategy (QSqlTableModel::OnRowChange); + m_->setEditStrategy (QSqlTableModel::OnFieldChange); } } diff --git a/models/FoxLog.cpp b/models/FoxLog.cpp index 1503e5662..691647fdc 100644 --- a/models/FoxLog.cpp +++ b/models/FoxLog.cpp @@ -43,7 +43,7 @@ FoxLog::impl::impl () SQL_error_check (dupe_query_, &QSqlQuery::prepare, "SELECT COUNT(*) FROM fox_log WHERE call = :call AND band = :band"); - setEditStrategy (QSqlTableModel::OnRowChange); + setEditStrategy (QSqlTableModel::OnFieldChange); setTable ("fox_log"); setHeaderData (fieldIndex ("when"), Qt::Horizontal, tr ("Date & Time(UTC)")); setHeaderData (fieldIndex ("call"), Qt::Horizontal, tr ("Call")); @@ -100,6 +100,10 @@ bool FoxLog::add_QSO (QDateTime const& when, QString const& call, QString const& set_value_maybe_null (record, "report_sent", report_sent); set_value_maybe_null (record, "report_rcvd", report_received); set_value_maybe_null (record, "band", band); + if (m_->isDirty ()) + { + m_->revert (); // discard any uncommitted changes + } auto ok = m_->insertRecord (-1, record); if (ok) { @@ -126,6 +130,6 @@ void FoxLog::reset () SQL_error_check (*m_, &QSqlTableModel::removeRows, 0, m_->rowCount (), QModelIndex {}); transaction.submit (); m_->select (); // to refresh views - m_->setEditStrategy (QSqlTableModel::OnRowChange); + m_->setEditStrategy (QSqlTableModel::OnFieldChange); } } diff --git a/widgets/CabrilloLogWindow.cpp b/widgets/CabrilloLogWindow.cpp index 20f39e4e6..4bf70f805 100644 --- a/widgets/CabrilloLogWindow.cpp +++ b/widgets/CabrilloLogWindow.cpp @@ -66,7 +66,7 @@ CabrilloLogWindow::CabrilloLogWindow (QSettings * settings, Configuration const set_log_view (m_->ui_.log_table_view); m_->ui_.log_table_view->setItemDelegateForColumn (2, new DateTimeAsSecsSinceEpochDelegate {this}); m_->ui_.log_table_view->setItemDelegateForColumn (3, new CallsignDelegate {this}); - m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), m_->log_model_, 0, 6, this}); + m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), 0, this}); m_->ui_.log_table_view->horizontalHeader ()->moveSection (6, 1); // band to first column } diff --git a/widgets/FoxLogWindow.cpp b/widgets/FoxLogWindow.cpp index 0f96529aa..4b8fbc253 100644 --- a/widgets/FoxLogWindow.cpp +++ b/widgets/FoxLogWindow.cpp @@ -43,7 +43,7 @@ FoxLogWindow::FoxLogWindow (QSettings * settings, Configuration const * configur m_->ui_.log_table_view->setItemDelegateForColumn (1, new DateTimeAsSecsSinceEpochDelegate {this}); m_->ui_.log_table_view->setItemDelegateForColumn (2, new CallsignDelegate {this}); m_->ui_.log_table_view->setItemDelegateForColumn (3, new MaidenheadLocatorDelegate {this}); - m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), m_->log_model_, 0, 6, this}); + m_->ui_.log_table_view->setItemDelegateForColumn (6, new ForeignKeyDelegate {configuration->bands (), 0, this}); m_->ui_.log_table_view->horizontalHeader ()->moveSection (6, 1); // move band to first column m_->ui_.rate_label->setNum (0); m_->ui_.queued_label->setNum (0); diff --git a/widgets/logqso.cpp b/widgets/logqso.cpp index e5b8a2e56..da8d00819 100644 --- a/widgets/logqso.cpp +++ b/widgets/logqso.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include "logbook/logbook.h" #include "MessageBox.hpp" @@ -70,7 +69,7 @@ void LogQSO::initLogQSO(QString const& hisCall, QString const& hisGrid, QString if (ui->cbTxPower->isChecked ()) ui->txPower->setText(m_txPower); if (ui->cbComments->isChecked ()) ui->comments->setText(m_comments); if (m_config->report_in_comments()) { - QString t=mode; + auto t=mode; if(rptSent!="") t+=" Sent: " + rptSent; if(rptRcvd!="") t+=" Rcvd: " + rptRcvd; ui->comments->setText(t); @@ -108,30 +107,28 @@ void LogQSO::initLogQSO(QString const& hisCall, QString const& hisGrid, QString void LogQSO::accept() { - QString hisCall,hisGrid,mode,rptSent,rptRcvd,dateOn,dateOff,timeOn,timeOff,band,operator_call; - QString comments,name; - - hisCall=ui->call->text(); - hisGrid=ui->grid->text(); - mode=ui->mode->text(); - rptSent=ui->sent->text(); - rptRcvd=ui->rcvd->text(); - m_dateTimeOn = ui->start_date_time->dateTime (); - m_dateTimeOff = ui->end_date_time->dateTime (); - band=ui->band->text(); - name=ui->name->text(); - m_txPower=ui->txPower->text(); - comments=ui->comments->text(); - m_comments=comments; - QString strDialFreq(QString::number(m_dialFreq / 1.e6,'f',6)); - operator_call = ui->loggedOperator->text(); + auto hisCall = ui->call->text (); + auto hisGrid = ui->grid->text (); + auto mode = ui->mode->text (); + auto rptSent = ui->sent->text (); + auto rptRcvd = ui->rcvd->text (); + auto m_dateTimeOn = ui->start_date_time->dateTime (); + auto m_dateTimeOff = ui->end_date_time->dateTime (); + auto band = ui->band->text (); + auto name = ui->name->text (); + auto m_txPower = ui->txPower->text (); + auto m_comments = ui->comments->text (); + auto strDialFreq = QString::number (m_dialFreq / 1.e6,'f',6); + auto operator_call = ui->loggedOperator->text (); + auto xsent = ui->exchSent->text (); + auto xrcvd = ui->exchRcvd->text (); // validate using SpOp = Configuration::SpecialOperatingActivity; auto special_op = m_config->special_op_id (); if (SpOp::NONE < special_op && special_op < SpOp::FOX) { - if (ui->exchSent->text ().isEmpty () || ui->exchRcvd->text ().isEmpty ()) + if (xsent.isEmpty () || xrcvd.isEmpty ()) { show (); MessageBox::warning_message (this, tr ("Invalid QSO Data"), @@ -139,8 +136,7 @@ void LogQSO::accept() return; // without accepting } - if (!m_cabrilloLog->add_QSO (m_dialFreq, m_dateTimeOff, hisCall, - ui->exchSent->text (), ui->exchRcvd->text ())) + if (!m_cabrilloLog->add_QSO (m_dialFreq, m_dateTimeOff, hisCall, xsent, xrcvd)) { show (); MessageBox::warning_message (this, tr ("Invalid QSO Data"), @@ -162,7 +158,7 @@ void LogQSO::accept() m_dateTimeOff.time().toString("hh:mm:ss,") + hisCall + "," + hisGrid + "," + strDialFreq + "," + mode + "," + rptSent + "," + rptRcvd + "," + m_txPower + - "," + comments + "," + name; + "," + m_comments + "," + name; QTextStream out(&f); out << logEntry << endl; f.close(); @@ -177,12 +173,14 @@ void LogQSO::accept() , rptSent , rptRcvd , m_txPower - , comments + , m_comments , name , m_dateTimeOn , operator_call , m_myCall , m_myGrid + , xsent + , xrcvd , LogBook::QSOToADIF (hisCall , hisGrid , mode @@ -191,15 +189,15 @@ void LogQSO::accept() , m_dateTimeOn , m_dateTimeOff , band - , comments + , m_comments , name , strDialFreq , m_myCall , m_myGrid , m_txPower , operator_call - , ui->exchSent->text () - , ui->exchRcvd->text ())); + , xsent + , xrcvd)); QDialog::accept(); } diff --git a/widgets/logqso.h b/widgets/logqso.h index b0e703a93..346e3e5a2 100644 --- a/widgets/logqso.h +++ b/widgets/logqso.h @@ -40,7 +40,9 @@ signals: , 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& my_call, QString const& my_grid, QByteArray const& ADIF); + , QString const& my_call, QString const& my_grid + , QString const& exchange_sent, QString const& exchange_rcvd + , QByteArray const& ADIF); protected: void hideEvent (QHideEvent *); diff --git a/widgets/logqso.ui b/widgets/logqso.ui index 75ca35db3..a03a3028a 100644 --- a/widgets/logqso.ui +++ b/widgets/logqso.ui @@ -81,6 +81,9 @@ dd/MM/yyyy HH:mm:ss + + Qt::UTC + @@ -113,6 +116,9 @@ dd/MM/yyyy HH:mm:ss + + Qt::UTC + diff --git a/widgets/mainwindow.cpp b/widgets/mainwindow.cpp index 97e025931..b265ad7ba 100644 --- a/widgets/mainwindow.cpp +++ b/widgets/mainwindow.cpp @@ -188,7 +188,7 @@ namespace int ms_minute_error () { - auto const& now = QDateTime::currentDateTime (); + auto const& now = QDateTime::currentDateTimeUtc (); auto const& time = now.time (); auto second = time.second (); return now.msecsTo (now.addSecs (second > 30 ? 60 - second : -second)) - time.msec (); @@ -1508,7 +1508,7 @@ QString MainWindow::save_wave_file (QString const& name, short const * data, int BWFFile::InfoDictionary list_info { {{{'I','S','R','C'}}, source.toLocal8Bit ()}, {{{'I','S','F','T'}}, program_title (revision ()).simplified ().toLocal8Bit ()}, - {{{'I','C','R','D'}}, QDateTime::currentDateTime () + {{{'I','C','R','D'}}, QDateTime::currentDateTimeUtc () .toString ("yyyy-MM-ddTHH:mm:ss.zzzZ").toLocal8Bit ()}, {{{'I','C','M','T'}}, comment.toLocal8Bit ()}, }; @@ -2712,7 +2712,7 @@ void MainWindow::msgAvgDecode2() void MainWindow::decode() //decode() { - QDateTime now = QDateTime::currentDateTime(); + QDateTime now = QDateTime::currentDateTimeUtc (); if( m_dateTimeLastTX.isValid () ) { qint64 isecs_since_tx = m_dateTimeLastTX.secsTo(now); dec_data.params.lapcqonly= (isecs_since_tx > 600); @@ -3266,7 +3266,7 @@ void MainWindow::pskPost (DecodedText const& decodedtext) if(grid.contains (grid_regexp)) { // qDebug() << "To PSKreporter:" << deCall << grid << frequency << msgmode << snr; psk_Reporter->addRemoteStation(deCall,grid,QString::number(frequency),msgmode, - QString::number(snr),QString::number(QDateTime::currentDateTime().toTime_t())); + QString::number(snr),QString::number(QDateTime::currentDateTimeUtc ().toTime_t())); } } @@ -3399,7 +3399,7 @@ void MainWindow::guiUpdate() if(m_tune) m_bTxTime=true; //"Tune" takes precedence if(m_transmitting or m_auto or m_tune) { - m_dateTimeLastTX = QDateTime::currentDateTime (); + m_dateTimeLastTX = QDateTime::currentDateTimeUtc (); // Check for "txboth" (testing purposes only) QFile f(m_appDir + "/txboth"); @@ -5376,7 +5376,9 @@ void MainWindow::acceptQSO (QDateTime const& QSO_date_off, QString const& call, , 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& my_call, QString const& my_grid, QByteArray const& ADIF) + , QString const& my_call, QString const& my_grid + , QString const& exchange_sent, QString const& exchange_rcvd + , QByteArray const& ADIF) { QString date = QSO_date_on.toString("yyyyMMdd"); if (!m_logBook.add (m_hisCall, grid, m_config.bands()->find(m_freqNominal), m_modeTx, ADIF)) @@ -5386,7 +5388,8 @@ void MainWindow::acceptQSO (QDateTime const& QSO_date_off, QString const& 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); + , tx_power, comments, name, QSO_date_on, operator_call, my_call, my_grid + , exchange_sent, exchange_rcvd); m_messageClient->logged_ADIF (ADIF); // Log to N1MM Logger @@ -7681,7 +7684,8 @@ void MainWindow::statusUpdate () const ui->RxFreqSpinBox->value (), ui->TxFreqSpinBox->value (), m_config.my_callsign (), m_config.my_grid (), m_hisGrid, m_tx_watchdog, - submode != QChar::Null ? QString {submode} : QString {}, m_bFastMode); + submode != QChar::Null ? QString {submode} : QString {}, m_bFastMode, + static_cast (m_config.special_op_id ())); } void MainWindow::childEvent (QChildEvent * e) diff --git a/widgets/mainwindow.h b/widgets/mainwindow.h index e8f593c3f..6a2527440 100644 --- a/widgets/mainwindow.h +++ b/widgets/mainwindow.h @@ -230,7 +230,9 @@ private slots: , 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& my_call, QString const& my_grid, QByteArray const& ADIF); + , QString const& my_call, QString const& my_grid + , QString const& exchange_sent, QString const& exchange_rcvd + , QByteArray const& ADIF); void on_bandComboBox_currentIndexChanged (int index); void on_bandComboBox_activated (int index); void on_readFreq_clicked();